build 170810. multi-texture materials, reflection map support

This commit is contained in:
tmj-fstate
2017-08-10 18:19:21 +02:00
parent bc22d582de
commit 611ebed7ab
25 changed files with 687 additions and 430 deletions

View File

@@ -440,14 +440,15 @@ bool TAnimModel::Init(TModel3d *pNewModel)
bool TAnimModel::Init(std::string const &asName, std::string const &asReplacableTexture)
{
if (asReplacableTexture.substr(0, 1) ==
"*") // od gwiazdki zaczynają się teksty na wyświetlaczach
asText = asReplacableTexture.substr(1, asReplacableTexture.length() - 1); // zapamiętanie tekstu
else if (asReplacableTexture != "none")
m_materialdata.replacable_skins[1] =
GfxRenderer.Fetch_Texture( asReplacableTexture, "" );
if( ( m_materialdata.replacable_skins[ 1 ] != 0 )
&& ( GfxRenderer.Texture( m_materialdata.replacable_skins[ 1 ] ).has_alpha ) ) {
if( asReplacableTexture.substr( 0, 1 ) == "*" ) {
// od gwiazdki zaczynają się teksty na wyświetlaczach
asText = asReplacableTexture.substr( 1, asReplacableTexture.length() - 1 ); // zapamiętanie tekstu
}
else if( asReplacableTexture != "none" ) {
m_materialdata.replacable_skins[ 1 ] = GfxRenderer.Fetch_Material( asReplacableTexture );
}
if( ( m_materialdata.replacable_skins[ 1 ] != NULL )
&& ( GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).has_alpha ) ) {
// tekstura z kanałem alfa - nie renderować w cyklu nieprzezroczystych
m_materialdata.textures_alpha = 0x31310031;
}

View File

@@ -15,7 +15,7 @@ http://mozilla.org/MPL/2.0/.
#pragma once
#include "Model3d.h"
#include "Texture.h"
#include "material.h"
#include "DynObj.h"
const int iMaxNumLights = 8;

View File

@@ -4591,20 +4591,20 @@ bool TController::UpdateSituation(double dt)
// if not MinVelFlag)
if (fBrakeTime < 0 ? true : (AccDesired < fAccGravity - 0.3) ||
(mvOccupied->BrakeCtrlPos <= 0))
if (!IncBrake()) // jeśli upłynął czas reakcji hamulca, chyba że
// nagłe albo luzował
if( false == IncBrake() ) {
// jeśli upłynął czas reakcji hamulca, chyba że nagłe albo luzował
MinVelFlag = true;
else
{
}
else {
MinVelFlag = false;
fBrakeTime =
3 +
0.5 *
(mvOccupied
->BrakeDelay[2 + 2 * mvOccupied->BrakeDelayFlag] -
3);
// Ra: ten czas należy zmniejszyć, jeśli czas dojazdu do
// zatrzymania jest mniejszy
3.0
+ 0.5 * ( (
mvOccupied->BrakeDelayFlag > bdelay_G ?
mvOccupied->BrakeDelay[ 1 ] :
mvOccupied->BrakeDelay[ 3 ] )
- 3.0 );
// Ra: ten czas należy zmniejszyć, jeśli czas dojazdu do zatrzymania jest mniejszy
fBrakeTime *= 0.5; // Ra: tymczasowo, bo przeżyna S1
}
if ((AccDesired < fAccGravity - 0.05) && (AbsAccS < AccDesired - 0.2))
@@ -4613,11 +4613,15 @@ bool TController::UpdateSituation(double dt)
// if (fBrakeTime<0)
{ // jak hamuje, to nie tykaj kranu za często
// yB: luzuje hamulec dopiero przy różnicy opóźnień rzędu 0.2
if (OrderList[OrderPos] !=
Disconnect) // przy odłączaniu nie zwalniamy tu hamulca
if( OrderList[ OrderPos ] != Disconnect ) {
// przy odłączaniu nie zwalniamy tu hamulca
DecBrake(); // tutaj zmniejszało o 1 przy odczepianiu
fBrakeTime =
(mvOccupied->BrakeDelay[1 + 2 * mvOccupied->BrakeDelayFlag]) / 3.0;
}
fBrakeTime = (
mvOccupied->BrakeDelayFlag > bdelay_G ?
mvOccupied->BrakeDelay[ 0 ] :
mvOccupied->BrakeDelay[ 2 ] )
/ 3.0;
fBrakeTime *= 0.5; // Ra: tymczasowo, bo przeżyna S1
}
}

View File

@@ -4036,7 +4036,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
{
std::string nowheretexture = TextureTest(Global::asCurrentTexturePath + "nowhere"); // na razie prymitywnie
if( false == nowheretexture.empty() ) {
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Texture( nowheretexture, "", 9 );
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Material( nowheretexture );
}
if (m_materialdata.multi_textures > 0) {
@@ -4048,7 +4048,7 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
int skinindex = 0;
std::string texturename; nameparser >> texturename;
while( ( texturename != "" ) && ( skinindex < 4 ) ) {
m_materialdata.replacable_skins[ skinindex + 1 ] = GfxRenderer.Fetch_Texture( Global::asCurrentTexturePath + texturename, "" );
m_materialdata.replacable_skins[ skinindex + 1 ] = GfxRenderer.Fetch_Material( Global::asCurrentTexturePath + texturename );
++skinindex;
texturename = ""; nameparser >> texturename;
}
@@ -4058,24 +4058,24 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
// otherwise try the basic approach
int skinindex = 0;
do {
texture_handle texture = GfxRenderer.Fetch_Texture( Global::asCurrentTexturePath + ReplacableSkin + "," + std::to_string( skinindex + 1 ), "", Global::iDynamicFiltering, true );
if( texture == NULL ) {
material_handle material = GfxRenderer.Fetch_Material( Global::asCurrentTexturePath + ReplacableSkin + "," + std::to_string( skinindex + 1 ), true );
if( material == NULL ) {
break;
}
m_materialdata.replacable_skins[ skinindex + 1 ] = texture;
m_materialdata.replacable_skins[ skinindex + 1 ] = material;
++skinindex;
} while( skinindex < 4 );
m_materialdata.multi_textures = skinindex;
if( m_materialdata.multi_textures == 0 ) {
// zestaw nie zadziałał, próbujemy normanie
m_materialdata.replacable_skins[ 1 ] = GfxRenderer.Fetch_Texture( Global::asCurrentTexturePath + ReplacableSkin, "", Global::iDynamicFiltering );
m_materialdata.replacable_skins[ 1 ] = GfxRenderer.Fetch_Material( Global::asCurrentTexturePath + ReplacableSkin );
}
}
}
else {
m_materialdata.replacable_skins[ 1 ] = GfxRenderer.Fetch_Texture( Global::asCurrentTexturePath + ReplacableSkin, "", Global::iDynamicFiltering );
m_materialdata.replacable_skins[ 1 ] = GfxRenderer.Fetch_Material( Global::asCurrentTexturePath + ReplacableSkin );
}
if( GfxRenderer.Texture( m_materialdata.replacable_skins[ 1 ] ).has_alpha ) {
if( GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).has_alpha ) {
// tekstura -1 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
m_materialdata.textures_alpha = 0x31310031;
}
@@ -4085,17 +4085,17 @@ void TDynamicObject::LoadMMediaFile(std::string BaseDir, std::string TypeName,
}
if( ( m_materialdata.replacable_skins[ 2 ] )
&& ( GfxRenderer.Texture( m_materialdata.replacable_skins[ 2 ] ).has_alpha ) ) {
&& ( GfxRenderer.Material( m_materialdata.replacable_skins[ 2 ] ).has_alpha ) ) {
// tekstura -2 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
m_materialdata.textures_alpha |= 0x02020002;
}
if( ( m_materialdata.replacable_skins[ 3 ] )
&& ( GfxRenderer.Texture( m_materialdata.replacable_skins[ 3 ] ).has_alpha ) ) {
&& ( GfxRenderer.Material( m_materialdata.replacable_skins[ 3 ] ).has_alpha ) ) {
// tekstura -3 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
m_materialdata.textures_alpha |= 0x04040004;
}
if( ( m_materialdata.replacable_skins[ 4 ] )
&& ( GfxRenderer.Texture( m_materialdata.replacable_skins[ 4 ] ).has_alpha ) ) {
&& ( GfxRenderer.Material( m_materialdata.replacable_skins[ 4 ] ).has_alpha ) ) {
// tekstura -4 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
m_materialdata.textures_alpha |= 0x08080008;
}
@@ -5371,7 +5371,7 @@ int TDynamicObject::RouteWish(TTrack *tr)
std::string TDynamicObject::TextureTest(std::string const &name)
{ // Ra 2015-01: sprawdzenie dostępności tekstury o podanej nazwie
std::vector<std::string> extensions = { ".dds", ".tga", ".bmp" };
std::vector<std::string> extensions = { ".mat", ".dds", ".tga", ".bmp" };
for( auto const &extension : extensions ) {
if( true == FileExists( name + extension ) ) {
return name + extension;
@@ -5393,36 +5393,22 @@ void TDynamicObject::DestinationSet(std::string to, std::string numer)
numer = Global::Bezogonkow(numer);
asDestination = to;
to = Global::Bezogonkow(to); // do szukania pliku obcinamy ogonki
std::string x = TextureTest(asBaseDir + numer + "@" + MoverParameters->TypeName);
if (!x.empty())
{
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Texture( x, "", 9 ); // rozmywania 0,1,4,5 nie nadają się
return;
std::vector<std::string> destinations = {
asBaseDir + numer + "@" + MoverParameters->TypeName,
asBaseDir + numer,
asBaseDir + to + "@" + MoverParameters->TypeName,
asBaseDir + to,
asBaseDir + "nowhere" };
for( auto const &destination : destinations ) {
auto material = TextureTest( destination );
if( false == material.empty() ) {
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Material( material );
break;
}
}
x = TextureTest(asBaseDir + numer );
if (!x.empty())
{
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Texture( x, "", 9 ); // rozmywania 0,1,4,5 nie nadają się
return;
}
if (to.empty())
to = "nowhere";
x = TextureTest(asBaseDir + to + "@" + MoverParameters->TypeName); // w pierwszej kolejności z nazwą FIZ/MMD
if (!x.empty())
{
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Texture( x, "", 9 ); // rozmywania 0,1,4,5 nie nadają się
return;
}
x = TextureTest(asBaseDir + to); // na razie prymitywnie
if (!x.empty())
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Texture( x, "", 9 ); // rozmywania 0,1,4,5 nie nadają się
else
{
x = TextureTest(asBaseDir + "nowhere"); // jak nie znalazł dedykowanej, to niech daje nowhere
if (!x.empty())
m_materialdata.replacable_skins[ 4 ] = GfxRenderer.Fetch_Texture( x, "", 9 );
}
// Ra 2015-01: żeby zalogować błąd, trzeba by mieć pewność, że model używa tekstury nr 4
};
void TDynamicObject::OverheadTrack(float o)

View File

@@ -143,7 +143,7 @@ class TAnim
struct material_data {
int textures_alpha{ 0x30300030 }; // maska przezroczystości tekstur. default: tekstury wymienne nie mają przezroczystości
texture_handle replacable_skins[ 5 ] = { NULL, NULL, NULL, NULL, NULL }; // McZapkie:zmienialne nadwozie
material_handle replacable_skins[ 5 ] = { NULL, NULL, NULL, NULL, NULL }; // McZapkie:zmienialne nadwozie
int multi_textures{ 0 }; //<0 tekstury wskazane wpisem, >0 tekstury z przecinkami, =0 jedna
};

View File

@@ -67,7 +67,7 @@ TGroundNode::TGroundNode()
nNext = nNext2 = NULL;
iCount = 0; // wierzchołków w trójkącie
// iNumPts=0; //punktów w linii
TextureID = 0;
m_material = 0;
iFlags = 0; // tryb przezroczystości nie zbadany
Pointer = NULL; // zerowanie wskaźnika kontekstowego
bVisible = false; // czy widoczny
@@ -508,7 +508,7 @@ TGroundRect::mergeable( TGroundNode const &Left, TGroundNode const &Right ) {
// since view ranges and transparency type for all nodes put through this method are guaranteed to be equal,
// we can skip their tests and only do the material check.
// TODO, TBD: material as dedicated type, and refactor this method into a simple equality test
return ( ( Left.TextureID == Right.TextureID )
return ( ( Left.m_material == Right.m_material )
&& ( Left.Ambient == Right.Ambient )
&& ( Left.Diffuse == Right.Diffuse )
&& ( Left.Specular == Right.Specular ) );
@@ -776,7 +776,7 @@ void TGround::RaTriangleDivider(TGroundNode *node)
TGroundNode *ntri; // wskaźnik na nowy trójkąt
ntri = new TGroundNode(GL_TRIANGLES); // a ten jest nowy
// kopiowanie parametrów, przydałby się konstruktor kopiujący
ntri->TextureID = node->TextureID;
ntri->m_material = node->m_material;
ntri->iFlags = node->iFlags;
ntri->Ambient = node->Ambient;
ntri->Diffuse = node->Diffuse;
@@ -1376,23 +1376,36 @@ TGroundNode * TGround::AddGroundNode(cParser *parser)
*parser >> token;
}
str = token;
tmp->TextureID = GfxRenderer.Fetch_Texture( str );
tmp->m_material = GfxRenderer.Fetch_Material( str );
auto const texturehandle = (
tmp->m_material != NULL ?
GfxRenderer.Material( tmp->m_material ).texture1 :
NULL );
auto const &texture = (
texturehandle ?
GfxRenderer.Texture( texturehandle ) :
opengl_texture() ); // dirty workaround for lack of better api
bool const clamps = (
tmp->TextureID ?
GfxRenderer.Texture( tmp->TextureID ).traits.find( 's' ) != std::string::npos :
texturehandle ?
texture.traits.find( 's' ) != std::string::npos :
false );
bool const clampt = (
tmp->TextureID ?
GfxRenderer.Texture( tmp->TextureID ).traits.find( 't' ) != std::string::npos :
texturehandle ?
texture.traits.find( 't' ) != std::string::npos :
false );
tmp->iFlags |= 200; // z usuwaniem
// remainder of legacy 'problend' system -- geometry assigned a texture with '@' in its name is treated as translucent, opaque otherwise
tmp->iFlags |= (
( ( str.find( '@' ) != std::string::npos )
&& ( true == GfxRenderer.Texture( tmp->TextureID ).has_alpha ) ) ?
0x20 :
0x10 );
if( texturehandle != NULL ) {
tmp->iFlags |= (
( ( texture.name.find( '@' ) != std::string::npos )
&& ( true == texture.has_alpha ) ) ?
0x20 :
0x10 );
}
else {
tmp->iFlags |= 0x10;
}
TGroundVertex vertex, vertex1, vertex2;
std::size_t vertexcount{ 0 };

View File

@@ -15,7 +15,7 @@ http://mozilla.org/MPL/2.0/.
#include "VBO.h"
#include "Classes.h"
#include "ResourceManager.h"
#include "Texture.h"
#include "material.h"
#include "dumb3d.h"
#include "Float3d.h"
#include "Names.h"
@@ -140,7 +140,7 @@ public:
int iCount; // dla terenu
};
int iFlags; // tryb przezroczystości: 0x10-nieprz.,0x20-przezroczysty,0x30-mieszany
texture_handle TextureID; // główna (jedna) tekstura obiektu
material_handle m_material; // główna (jedna) tekstura obiektu
glm::vec3
Ambient{ 1.0f, 1.0f, 1.0f },
Diffuse{ 1.0f, 1.0f, 1.0f },

View File

@@ -63,16 +63,16 @@ TSubModel::~TSubModel()
// wyświetlania
};
void TSubModel::TextureNameSet(std::string const &Name)
void TSubModel::Name_Material(std::string const &Name)
{ // ustawienie nazwy submodelu, o
// ile nie jest wczytany z E3D
if (iFlags & 0x0200)
{ // tylko jeżeli submodel zosta utworzony przez new
pTexture = Name;
m_materialname = Name;
}
};
void TSubModel::NameSet(std::string const &Name)
void TSubModel::Name(std::string const &Name)
{ // ustawienie nazwy submodelu, o ile
// nie jest wczytany z E3D
if (iFlags & 0x0200)
@@ -177,7 +177,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
std::string token;
parser.getTokens(1, false); // nazwa submodelu bez zmieny na małe
parser >> token;
NameSet(token);
Name(token);
if (dynamic) {
// dla pojazdu, blokujemy załączone submodele, które mogą być nieobsługiwane
if( ( token.size() >= 3 )
@@ -305,50 +305,51 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
*/
if (!parser.expectToken("map:"))
Error("Model map parse failure!");
std::string texture = parser.getToken<std::string>();
if (texture == "none")
std::string material = parser.getToken<std::string>();
if (material == "none")
{ // rysowanie podanym kolorem
TextureID = 0;
m_material = NULL;
iFlags |= 0x10; // rysowane w cyklu nieprzezroczystych
}
else if (texture.find("replacableskin") != texture.npos)
else if (material.find("replacableskin") != material.npos)
{ // McZapkie-060702: zmienialne skory modelu
TextureID = -1;
m_material = -1;
iFlags |= (Opacity < 1.0) ? 1 : 0x10; // zmienna tekstura 1
}
else if (texture == "-1")
else if (material == "-1")
{
TextureID = -1;
m_material = -1;
iFlags |= (Opacity < 1.0) ? 1 : 0x10; // zmienna tekstura 1
}
else if (texture == "-2")
else if (material == "-2")
{
TextureID = -2;
m_material = -2;
iFlags |= (Opacity < 1.0) ? 2 : 0x10; // zmienna tekstura 2
}
else if (texture == "-3")
else if (material == "-3")
{
TextureID = -3;
m_material = -3;
iFlags |= (Opacity < 1.0) ? 4 : 0x10; // zmienna tekstura 3
}
else if (texture == "-4")
else if (material == "-4")
{
TextureID = -4;
m_material = -4;
iFlags |= (Opacity < 1.0) ? 8 : 0x10; // zmienna tekstura 4
}
else
{ // jeśli tylko nazwa pliku, to dawać bieżącą ścieżkę do tekstur
TextureNameSet(texture);
if( texture.find_first_of( "/\\" ) == texture.npos ) {
texture.insert( 0, Global::asCurrentTexturePath );
Name_Material(material);
if( material.find_first_of( "/\\" ) == material.npos ) {
material.insert( 0, Global::asCurrentTexturePath );
}
TextureID = GfxRenderer.Fetch_Texture( texture );
m_material = GfxRenderer.Fetch_Material( material );
// renderowanie w cyklu przezroczystych tylko jeśli:
// 1. Opacity=0 (przejściowo <1, czy tam <100) oraz
// 2. tekstura ma przezroczystość
iFlags |=
( ( ( Opacity < 1.0 )
&& ( GfxRenderer.Texture(TextureID).has_alpha ) ) ?
&& ( ( m_material != NULL )
&& ( GfxRenderer.Material( m_material ).has_alpha ) ) ) ?
0x20 :
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
};
@@ -591,10 +592,10 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
return iNumVerts; // do określenia wielkości VBO
};
int TSubModel::TriangleAdd(TModel3d *m, texture_handle tex, int tri)
int TSubModel::TriangleAdd(TModel3d *m, material_handle tex, int tri)
{ // dodanie trójkątów do submodelu, używane przy tworzeniu E3D terenu
TSubModel *s = this;
while (s ? (s->TextureID != tex) : false)
while (s ? (s->m_material != tex) : false)
{ // szukanie submodelu o danej teksturze
if (s == this)
s = Child;
@@ -603,15 +604,15 @@ int TSubModel::TriangleAdd(TModel3d *m, texture_handle tex, int tri)
}
if (!s)
{
if (TextureID <= 0)
if (m_material <= 0)
s = this; // użycie głównego
else
{ // dodanie nowego submodelu do listy potomnych
s = new TSubModel();
m->AddTo(this, s);
}
s->TextureNameSet(GfxRenderer.Texture(tex).name);
s->TextureID = tex;
s->Name_Material(GfxRenderer.Material(tex).name);
s->m_material = tex;
s->eType = GL_TRIANGLES;
}
if (s->iNumVerts < 0)
@@ -672,7 +673,7 @@ void TSubModel::DisplayLists()
glVertex3dv(&Vertices[i].Point.x);
*/
glNormal3fv(glm::value_ptr(Vertices[i].normal));
glTexCoord2fv(glm::value_ptr(Vertices[i].texture));
glTexCoord2fv(glm::value_ptr(Vertices[i].material));
glVertex3fv(glm::value_ptr(Vertices[i].position));
};
glEnd();
@@ -806,8 +807,8 @@ int TSubModel::FlagsCheck()
int i = 0;
if (Child)
{ // Child jest renderowany po danym submodelu
if (Child->TextureID) // o ile ma teksturę
if (Child->TextureID != TextureID) // i jest ona inna niż rodzica
if (Child->m_material) // o ile ma teksturę
if (Child->m_material != m_material) // i jest ona inna niż rodzica
Child->iFlags |= 0x80; // to trzeba sprawdzać, jak z teksturami jest
i = Child->FlagsCheck();
iFlags |= 0x00FF0000 & ((i << 16) | (i) | (i >> 8)); // potomny, rodzeństwo i dzieci
@@ -825,8 +826,8 @@ int TSubModel::FlagsCheck()
if (Next)
{ // Next jest renderowany po danym submodelu (kolejność odwrócona
// po wczytaniu T3D)
if (TextureID) // o ile dany ma teksturę
if ((TextureID != Next->TextureID) ||
if (m_material) // o ile dany ma teksturę
if ((m_material != Next->m_material) ||
(i & 0x00800000)) // a ma inną albo dzieci zmieniają
iFlags |= 0x80; // to dany submodel musi sobie ją ustawiać
i = Next->FlagsCheck();
@@ -1085,9 +1086,9 @@ TSubModel::convert( TGroundNode &Groundnode ) const {
Groundnode.Ambient = f4Ambient;
Groundnode.Diffuse = f4Diffuse;
Groundnode.Specular = f4Specular;
Groundnode.TextureID = TextureID;
Groundnode.m_material = m_material;
Groundnode.iFlags = (
( true == GfxRenderer.Texture( TextureID ).has_alpha ) ?
( true == GfxRenderer.Material( m_material ).has_alpha ) ?
0x20 :
0x10 );
@@ -1379,10 +1380,10 @@ void TSubModel::serialize(std::ostream &s,
sn_utils::ls_int32(s, iNumVerts);
sn_utils::ls_int32(s, tVboPtr);
if (TextureID <= 0)
sn_utils::ls_int32(s, TextureID);
if (m_material <= 0)
sn_utils::ls_int32(s, m_material);
else
sn_utils::ls_int32(s, (int32_t)get_container_pos(textures, pTexture));
sn_utils::ls_int32(s, (int32_t)get_container_pos(textures, m_materialname));
sn_utils::ls_float32(s, fVisible);
sn_utils::ls_float32(s, fLight);
@@ -1727,27 +1728,29 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
pName = "";
if (iTexture > 0)
{ // obsługa stałej tekstury
auto const textureindex = static_cast<std::size_t>( iTexture );
if( textureindex < t->size() ) {
pTexture = t->at( textureindex );
if( pTexture.find_last_of( "/\\" ) == std::string::npos )
pTexture.insert( 0, Global::asCurrentTexturePath );
TextureID = GfxRenderer.Fetch_Texture( pTexture );
auto const materialindex = static_cast<std::size_t>( iTexture );
if( materialindex < t->size() ) {
m_materialname = t->at( materialindex );
if( m_materialname.find_last_of( "/\\" ) == std::string::npos ) {
m_materialname = Global::asCurrentTexturePath + m_materialname;
}
m_material = GfxRenderer.Fetch_Material( m_materialname );
if( ( iFlags & 0x30 ) == 0 ) {
// texture-alpha based fallback if for some reason we don't have opacity flag set yet
iFlags |=
( GfxRenderer.Texture( TextureID ).has_alpha ?
iFlags |= (
( ( m_material != NULL )
&& ( GfxRenderer.Material( m_material ).has_alpha ) ) ?
0x20 :
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
}
}
else {
ErrorLog( "Bad model: reference to non-existent texture index in sub-model" + ( pName.empty() ? "" : " \"" + pName + "\"" ) );
TextureID = NULL;
m_material = NULL;
}
}
else
TextureID = iTexture;
m_material = iTexture;
b_aAnim = b_Anim; // skopiowanie animacji do drugiego cyklu

View File

@@ -14,7 +14,7 @@ http://mozilla.org/MPL/2.0/.
#include "dumb3d.h"
#include "Float3d.h"
#include "VBO.h"
#include "Texture.h"
#include "material.h"
using namespace Math3D;
@@ -122,7 +122,7 @@ private:
TSubModel *Next { nullptr };
TSubModel *Child { nullptr };
geometry_handle m_geometry { NULL, NULL }; // geometry of the submodel
texture_handle TextureID { NULL }; // numer tekstury, -1 wymienna, 0 brak
material_handle m_material { NULL }; // numer tekstury, -1 wymienna, 0 brak
bool bWire { false }; // nie używane, ale wczytywane
float Opacity { 1.0f };
float f_Angle { 0.0f };
@@ -143,7 +143,7 @@ public:
TSubModel **smLetter{ nullptr }; // wskaźnik na tablicę submdeli do generoania tekstu (docelowo zapisać do E3D)
TSubModel *Parent{ nullptr }; // nadrzędny, np. do wymnażania macierzy
int iVisible{ 1 }; // roboczy stan widoczności
std::string pTexture; // robocza nazwa tekstury do zapisania w pliku binarnym
std::string m_materialname; // robocza nazwa tekstury do zapisania w pliku binarnym
std::string pName; // robocza nazwa
private:
int SeekFaceNormal( std::vector<unsigned int> const &Masks, int const Startface, unsigned int const Mask, glm::vec3 const &Position, vertex_array const &Vertices );
@@ -151,7 +151,7 @@ private:
public:
static size_t iInstance; // identyfikator egzemplarza, który aktualnie renderuje model
static texture_handle const *ReplacableSkinId;
static material_handle const *ReplacableSkinId;
static int iAlpha; // maska bitowa dla danego przebiegu
static double fSquareDist;
static TModel3d *pRoot;
@@ -162,7 +162,7 @@ public:
void NextAdd(TSubModel *SubModel);
TSubModel * NextGet() { return Next; };
TSubModel * ChildGet() { return Child; };
int TriangleAdd(TModel3d *m, texture_handle tex, int tri);
int TriangleAdd(TModel3d *m, material_handle tex, int tri);
/*
basic_vertex * TrianglePtr(int tex, int pos, glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular );
*/
@@ -186,13 +186,13 @@ public:
};
void InitialRotate(bool doit);
void BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t, std::vector<std::string> *n, bool dynamic);
void ReplacableSet(texture_handle const *r, int a)
void ReplacableSet(material_handle const *r, int a)
{
ReplacableSkinId = r;
iAlpha = a;
};
void TextureNameSet( std::string const &Name );
void NameSet( std::string const &Name );
void Name_Material( std::string const &Name );
void Name( std::string const &Name );
// Ra: funkcje do budowania terenu z E3D
int Flags() { return iFlags; };
void UnFlagNext() { iFlags &= 0x00FFFFFF; };
@@ -203,8 +203,8 @@ public:
return fMatrix ? *(fMatrix->TranslationGet()) + v_TransVector : v_TransVector; }
inline float3 Translation2Get() {
return *(fMatrix->TranslationGet()) + Child->Translation1Get(); }
int GetTextureId() {
return TextureID; }
material_handle GetMaterial() {
return m_material; }
void ParentMatrix(float4x4 *m);
float MaxY( float4x4 const &m );
void AdjustDist();

View File

@@ -291,21 +291,16 @@ void TPythonScreenRenderer::updateTexture()
sprintf(buff, "Sending texture id: %d w: %d h: %d", _textureId, width, height);
WriteLog(buff);
#endif // _PY_INT_MORE_LOG
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
GfxRenderer.Bind(_textureId);
/*
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
glPixelStorei( GL_PACK_ALIGNMENT, 1 );
*/
GfxRenderer.Bind_Material(_textureId);
// setup texture parameters
if( GLEW_VERSION_1_4 ) {
glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexEnvf( GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -1.0 );
}
else {
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
}
glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexEnvf( GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -1.0 );
// build texture
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData );
@@ -457,7 +452,7 @@ void TPythonScreens::init(cParser &parser, TModel3d *model, std::string const &n
WriteLog( "Python Screen: submodel " + subModelName + " not found - Ignoring screen" );
return; // nie ma takiego sub modelu w danej kabinie pomijamy
}
auto textureId = subModel->GetTextureId();
auto textureId = subModel->GetMaterial();
if (textureId <= 0)
{
WriteLog( "Python Screen: invalid texture id " + std::to_string(textureId) + " - Ignoring screen" );

View File

@@ -454,7 +454,7 @@ bool TSegment::RenderLoft( vertex_array &Output, Math3D::vector3 const &Origin,
void TSegment::Render()
{
vector3 pt;
GfxRenderer.Bind(0);
GfxRenderer.Bind_Material( NULL );
if (bCurve)
{

View File

@@ -244,50 +244,14 @@ bool TSoundsManager::Init(HWND hWnd) {
pDS = nullptr;
pDSNotify = nullptr;
HRESULT hr; //=222;
LPDIRECTSOUNDBUFFER pDSBPrimary = nullptr;
// Create IDirectSound using the primary sound device
hr = DirectSoundCreate(NULL, &pDS, NULL);
auto hr = ::DirectSoundCreate(NULL, &pDS, NULL);
if (hr != DS_OK) {
return false;
};
// Set coop level to DSSCL_PRIORITY
// if( FAILED( hr = pDS->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ) ) );
// return ;
pDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
// Get the primary buffer
DSBUFFERDESC dsbd;
ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
if (!Global::bInactivePause) // jeśli przełączony w tło ma nadal działać
dsbd.dwFlags |= DSBCAPS_GLOBALFOCUS; // to dźwięki mają być również słyszalne
dsbd.dwBufferBytes = 0;
dsbd.lpwfxFormat = NULL;
if( FAILED( hr = pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) ) {
return false;
}
// Set primary buffer format to 22kHz and 16-bit output.
WAVEFORMATEX wfx;
ZeroMemory(&wfx, sizeof(WAVEFORMATEX));
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2;
wfx.nSamplesPerSec = 44100;
wfx.wBitsPerSample = 16;
wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
if( FAILED( hr = pDSBPrimary->SetFormat( &wfx ) ) ) {
return false;
}
SAFE_RELEASE(pDSBPrimary);
pDS->SetCooperativeLevel(hWnd, DSSCL_NORMAL);
return true;
};

View File

@@ -506,18 +506,15 @@ opengl_texture::load_TGA() {
return;
}
resource_state
bool
opengl_texture::bind() {
if( false == is_ready ) {
create();
if( data_state != resource_state::good ) {
return data_state;
}
if( ( false == is_ready )
&& ( false == create() ) ) {
return false;
}
::glBindTexture( GL_TEXTURE_2D, id );
return data_state;
return true;
}
bool
@@ -645,40 +642,7 @@ opengl_texture::set_filtering() {
switch( trait ) {
case '#': { sharpen = true; break; }
/*
// legacy filter modes. TODO, TBD: get rid of them?
// let's just turn them off and see if anyone notices.
case '4': {
// najbliższy z tekstury
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
break;
}
case '5': {
//średnia z tekstury
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
break;
}
case '6': {
// najbliższy z mipmapy
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST );
break;
}
case '7': {
//średnia z mipmapy
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
break;
}
case '8': {
// najbliższy z dwóch mipmap
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR );
break;
}
case '9': {
//średnia z dwóch mipmap
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
break;
}
*/
default: { break; }
}
}
@@ -718,9 +682,27 @@ opengl_texture::downsize( GLuint const Format ) {
};
}
void
texture_manager::assign_units( GLint const Helper, GLint const Shadows, GLint const Normals, GLint const Diffuse ) {
m_units[ 0 ].unit = Helper;
m_units[ 1 ].unit = Shadows;
m_units[ 2 ].unit = Normals;
m_units[ 3 ].unit = Diffuse;
}
void
texture_manager::unit( GLint const Textureunit ) {
if( m_activeunit == Textureunit ) { return; }
m_activeunit = Textureunit;
::glActiveTexture( Textureunit );
}
// ustalenie numeru tekstury, wczytanie jeśli jeszcze takiej nie było
texture_handle
texture_manager::create( std::string Filename, std::string const &Dir, int const Filter, bool const Loadnow ) {
texture_manager::create( std::string Filename, bool const Loadnow ) {
if( Filename.find( '|' ) != std::string::npos )
Filename.erase( Filename.find( '|' ) ); // po | może być nazwa kolejnej tekstury
@@ -801,11 +783,7 @@ texture_manager::create( std::string Filename, std::string const &Dir, int const
auto texture = new opengl_texture();
texture->name = filename;
if( ( Filter > 0 ) && ( Filter < 10 ) ) {
// temporary. TODO, TBD: check how it's used and possibly get rid of it
traits += std::to_string( ( Filter < 4 ? Filter + 4 : Filter ) );
}
if( Filename.find('#') !=std::string::npos ) {
if( Filename.find('#') != std::string::npos ) {
// temporary code for legacy assets -- textures with names beginning with # are to be sharpened
traits += '#';
}
@@ -830,33 +808,37 @@ texture_manager::create( std::string Filename, std::string const &Dir, int const
};
void
texture_manager::bind( texture_handle const Texture ) {
texture_manager::bind( std::size_t const Unit, texture_handle const Texture ) {
m_textures[ Texture ].second = m_garbagecollector.timestamp();
if( ( Texture != 0 ) && ( Texture == m_activetexture ) ) {
if( Texture == m_units[ Unit ].texture ) {
// don't bind again what's already active
return;
}
// TODO: do binding in texture object, add support for other types
if( Texture != 0 ) {
// TBD, TODO: do binding in texture object, add support for other types than 2d
if( m_units[ Unit ].unit == NULL ) { return; }
unit( m_units[ Unit ].unit );
if( Texture != NULL ) {
#ifndef EU07_DEFERRED_TEXTURE_UPLOAD
// NOTE: we could bind dedicated 'error' texture here if the id isn't valid
::glBindTexture( GL_TEXTURE_2D, texture(Texture).id );
m_activetexture = Texture;
m_units[ Unit ].texture = Texture;
#else
if( texture( Texture ).bind() == resource_state::good ) {
m_activetexture = Texture;
if( true == texture( Texture ).bind() ) {
m_units[ Unit ].texture = Texture;
}
else {
// TODO: bind a special 'error' texture on failure
::glBindTexture( GL_TEXTURE_2D, NULL );
m_units[ Unit ].texture = NULL;
}
#endif
}
else {
::glBindTexture( GL_TEXTURE_2D, 0 );
m_activetexture = 0;
::glBindTexture( GL_TEXTURE_2D, NULL );
m_units[ Unit ].texture = NULL;
}
// all done
return;
@@ -879,7 +861,9 @@ void
texture_manager::update() {
if( m_garbagecollector.sweep() > 0 ) {
m_activetexture = -1;
for( auto &unit : m_units ) {
unit.texture = -1;
}
}
}
@@ -943,21 +927,10 @@ texture_manager::find_in_databank( std::string const &Texturename ) const {
std::string
texture_manager::find_on_disk( std::string const &Texturename ) const {
{
std::ifstream file( Texturename );
if( true == file.is_open() ) {
// success
return Texturename;
}
}
// if we fail make a last ditch attempt in the default textures directory
{
std::ifstream file( szTexturePath + Texturename );
if( true == file.is_open() ) {
// success
return szTexturePath + Texturename;
}
}
// no results either way, report failure
return "";
return(
FileExists( Texturename ) ? Texturename :
FileExists( szTexturePath + Texturename ) ? szTexturePath + Texturename :
"" );
}
//---------------------------------------------------------------------------

View File

@@ -31,7 +31,7 @@ struct opengl_texture {
// methods
void
load();
resource_state
bool
bind();
bool
create();
@@ -85,12 +85,17 @@ public:
texture_manager();
~texture_manager() { delete_textures(); }
texture_handle
create( std::string Filename, std::string const &Dir, int const Filter = -1, bool const Loadnow = true );
void
bind( texture_handle const Texture );
assign_units( GLint const Helper, GLint const Shadows, GLint const Normals, GLint const Diffuse );
void
unit( GLint const Textureunit );
texture_handle
create( std::string Filename, bool const Loadnow = true );
// binds specified texture to specified texture unit
void
bind( std::size_t const Unit, texture_handle const Texture );
opengl_texture &
texture( texture_handle const Texture ) { return *(m_textures[ Texture ].first); }
texture( texture_handle const Texture ) const { return *(m_textures[ Texture ].first); }
// performs a resource sweep
void
update();
@@ -108,6 +113,11 @@ private:
typedef std::unordered_map<std::string, std::size_t> index_map;
struct texture_unit {
GLint unit { NULL };
texture_handle texture { NULL }; // current (most recently bound) texture
};
// methods:
// checks whether specified texture is in the texture bank. returns texture id, or npos.
texture_handle
@@ -123,7 +133,8 @@ private:
texturetimepointpair_sequence m_textures;
index_map m_texturemappings;
garbage_collector<texturetimepointpair_sequence> m_garbagecollector { m_textures, 600, 60, "texture" };
texture_handle m_activetexture { 0 }; // last i.e. currently bound texture
std::array<texture_unit, 4> m_units;
GLint m_activeunit { NULL };
};
// reduces provided data image to half of original size, using basic 2x2 average
@@ -182,3 +193,5 @@ downsample( std::size_t const Width, std::size_t const Height, char *Imagedata )
}
}
}
//---------------------------------------------------------------------------

View File

@@ -483,20 +483,20 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
{
parser->getTokens();
*parser >> str; // railtex
TextureID1 = (
m_material1 = (
str == "none" ?
NULL :
GfxRenderer.Fetch_Texture( str ) );
GfxRenderer.Fetch_Material( str ) );
parser->getTokens();
*parser >> fTexLength; // tex tile length
if (fTexLength < 0.01)
fTexLength = 4; // Ra: zabezpiecznie przed zawieszeniem
parser->getTokens();
*parser >> str; // sub || railtex
TextureID2 = (
m_material2 = (
str == "none" ?
NULL :
GfxRenderer.Fetch_Texture( str ) );
GfxRenderer.Fetch_Material( str ) );
parser->getTokens(3);
*parser >> fTexHeight1 >> fTexWidth >> fTexSlope;
if (iCategoryFlag & 4)
@@ -547,15 +547,15 @@ void TTrack::Load(cParser *parser, vector3 pOrigin, std::string name)
SwitchExtension->Segments[0]->Init(p1, p2, segsize); // kopia oryginalnego toru
}
else if (iCategoryFlag & 2)
if (TextureID1 && fTexLength)
if (m_material1 && fTexLength)
{ // dla drogi trzeba ustalić proporcje boków nawierzchni
float w, h;
GfxRenderer.Bind(TextureID1);
GfxRenderer.Bind_Material(m_material1);
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
if (h != 0.0)
fTexRatio1 = w / h; // proporcja boków
GfxRenderer.Bind(TextureID2);
GfxRenderer.Bind_Material(m_material2);
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
if (h != 0.0)
@@ -1205,7 +1205,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
{
case tt_Table: // obrotnica jak zwykły tor, tylko animacja dochodzi
case tt_Normal:
if (TextureID2)
if (m_material2)
{ // podsypka z podkładami jest tylko dla zwykłego toru
vector6 bpts1[8]; // punkty głównej płaszczyzny nie przydają się do robienia boków
if (fTexLength == 4.0) // jeśli stare mapowanie
@@ -1275,7 +1275,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
GfxRenderer.Replace( vertices, Geometry2[ 0 ] );
}
}
if (TextureID1)
if (m_material1)
{ // szyny - generujemy dwie, najwyżej rysować się będzie jedną
vertex_array vertices;
if( ( Bank != 0 ) && ( true == Geometry1.empty() ) ) {
@@ -1296,7 +1296,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
}
break;
case tt_Switch: // dla zwrotnicy dwa razy szyny
if( TextureID1 || TextureID2 )
if( m_material1 || m_material2 )
{ // iglice liczone tylko dla zwrotnic
vector6 rpts3[24], rpts4[24];
for (i = 0; i < 12; ++i)
@@ -1326,7 +1326,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
if (SwitchExtension->RightSwitch)
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
vertex_array vertices;
if( TextureID1 ) {
if( m_material1 ) {
// fixed parts
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts2, nnumPts, fTexLength );
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
@@ -1339,7 +1339,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
vertices.clear();
}
if( TextureID2 ) {
if( m_material2 ) {
// fixed parts
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts1, nnumPts, fTexLength );
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
@@ -1356,7 +1356,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
else
{ // lewa działa lepiej niż prawa
vertex_array vertices;
if( TextureID1 ) {
if( m_material1 ) {
// fixed parts
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts1, nnumPts, fTexLength ); // lewa szyna normalna cała
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
@@ -1369,7 +1369,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
vertices.clear();
}
if( TextureID2 ) {
if( m_material2 ) {
// fixed parts
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts2, nnumPts, fTexLength ); // prawa szyna normalnie cała
Geometry2.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
@@ -1394,7 +1394,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
case tt_Normal: // drogi proste, bo skrzyżowania osobno
{
vector6 bpts1[4]; // punkty głównej płaszczyzny przydają się do robienia boków
if (TextureID1 || TextureID2) // punkty się przydadzą, nawet jeśli nawierzchni nie ma
if (m_material1 || m_material2) // punkty się przydadzą, nawet jeśli nawierzchni nie ma
{ // double max=2.0*(fHTW>fHTW2?fHTW:fHTW2); //z szerszej strony jest 100%
double max = fTexRatio1 * fTexLength; // test: szerokość proporcjonalna do długości
double map1 = max > 0.0 ? fHTW / max : 0.5; // obcięcie tekstury od strony 1
@@ -1413,13 +1413,13 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
bpts1[ 1 ] = vector6( -fHTW, 0.0, 0.5 + map1, 0.0, 1.0, 0.0 );
}
}
if (TextureID1) // jeśli podana była tekstura, generujemy trójkąty
if (m_material1) // jeśli podana była tekstura, generujemy trójkąty
{ // tworzenie trójkątów nawierzchni szosy
vertex_array vertices;
Segment->RenderLoft(vertices, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
}
if (TextureID2)
if (m_material2)
{ // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w Midtown Madness 2?)
vector6
rpts1[6],
@@ -1574,7 +1574,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
nullptr :
SwitchExtension->vPoints; // zmienna robocza, NULL gdy tablica punktów już jest wypełniona
vector6 bpts1[4]; // punkty głównej płaszczyzny przydają się do robienia boków
if (TextureID1 || TextureID2) // punkty się przydadzą, nawet jeśli nawierzchni nie ma
if (m_material1 || m_material2) // punkty się przydadzą, nawet jeśli nawierzchni nie ma
{ // double max=2.0*(fHTW>fHTW2?fHTW:fHTW2); //z szerszej strony jest 100%
double max = fTexRatio1 * fTexLength; // test: szerokość proporcjonalna do długości
double map1 = max > 0.0 ? fHTW / max : 0.5; // obcięcie tekstury od strony 1
@@ -1592,7 +1592,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
// problem ze skrzyżowaniami jest taki, że teren chce się pogrupować wg tekstur, ale zaczyna od nawierzchni
// sama nawierzchnia nie wypełni tablicy punktów, bo potrzebne są pobocza
// ale pobocza renderują się później, więc nawierzchnia nie załapuje się na renderowanie w swoim czasie
if( TextureID2 )
if( m_material2 )
{ // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w Midtown Madness 2?)
vector6
rpts1[6],
@@ -1651,7 +1651,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
rpts2[5] = vector6(bpts1[3].x - side2, bpts1[3].y - fTexHeight2, 0.484375 - map2l); // lewy brzeg lewego chodnika
}
}
bool render = ( TextureID2 != 0 ); // renderować nie trzeba, ale trzeba wyznaczyć punkty brzegowe nawierzchni
bool render = ( m_material2 != 0 ); // renderować nie trzeba, ale trzeba wyznaczyć punkty brzegowe nawierzchni
vertex_array vertices;
if (SwitchExtension->iRoads == 4)
{ // pobocza do trapezowatej nawierzchni - dodatkowe punkty z drugiej strony odcinka
@@ -1707,7 +1707,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
SwitchExtension->bPoints = true; // tablica punktów została wypełniona
}
if( TextureID1 ) {
if( m_material1 ) {
vertex_array vertices;
// jeśli podana tekstura nawierzchni
// we start with a vertex in the middle...
@@ -1759,7 +1759,7 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
case tt_Normal: // drogi proste, bo skrzyżowania osobno
{
vector6 bpts1[4]; // punkty głównej płaszczyzny przydają się do robienia boków
if (TextureID1 || TextureID2) // punkty się przydadzą, nawet jeśli nawierzchni nie ma
if (m_material1 || m_material2) // punkty się przydadzą, nawet jeśli nawierzchni nie ma
{ // double max=2.0*(fHTW>fHTW2?fHTW:fHTW2); //z szerszej strony jest 100%
double max = (iCategoryFlag & 4) ?
0.0 :
@@ -1784,13 +1784,13 @@ void TTrack::create_geometry( geometrybank_handle const &Bank ) {
bpts1[1] = vector6(-fHTW, 0.0, 0.5 + map1);
}
}
if (TextureID1) // jeśli podana była tekstura, generujemy trójkąty
if (m_material1) // jeśli podana była tekstura, generujemy trójkąty
{ // tworzenie trójkątów nawierzchni szosy
vertex_array vertices;
Segment->RenderLoft(vertices, origin, bpts1, iTrapezoid ? -2 : 2, fTexLength);
Geometry1.emplace_back( GfxRenderer.Insert( vertices, Bank, GL_TRIANGLE_STRIP ) );
}
if (TextureID2)
if (m_material2)
{ // pobocze drogi - poziome przy przechyłce (a może krawężnik i chodnik zrobić jak w Midtown Madness 2?)
vertex_array vertices;
vector6 rpts1[6],
@@ -2105,8 +2105,8 @@ TTrack * TTrack::RaAnimate()
}
}
// skip the geometry update if no geometry for this track was generated yet
if( ( ( TextureID1 != 0 )
|| ( TextureID2 != 0 ) )
if( ( ( m_material1 != 0 )
|| ( m_material2 != 0 ) )
&& ( ( false == Geometry1.empty() )
|| ( false == Geometry2.empty() ) ) ) {
// iglice liczone tylko dla zwrotnic
@@ -2143,13 +2143,13 @@ TTrack * TTrack::RaAnimate()
if (SwitchExtension->RightSwitch)
{ // nowa wersja z SPKS, ale odwrotnie lewa/prawa
if( TextureID1 ) {
if( m_material1 ) {
// left blade
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, SwitchExtension->fOffset2 );
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
vertices.clear();
}
if( TextureID2 ) {
if( m_material2 ) {
// right blade
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -fMaxOffset + SwitchExtension->fOffset1 );
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );
@@ -2157,13 +2157,13 @@ TTrack * TTrack::RaAnimate()
}
}
else { // lewa działa lepiej niż prawa
if( TextureID1 ) {
if( m_material1 ) {
// right blade
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, origin, rpts4, -nnumPts, fTexLength, 1.0, 0, 2, -SwitchExtension->fOffset2 );
GfxRenderer.Replace( vertices, Geometry1[ 2 ] );
vertices.clear();
}
if( TextureID2 ) {
if( m_material2 ) {
// left blade
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, origin, rpts3, -nnumPts, fTexLength, 1.0, 0, 2, fMaxOffset - SwitchExtension->fOffset1 );
GfxRenderer.Replace( vertices, Geometry2[ 2 ] );

10
Track.h
View File

@@ -13,7 +13,7 @@ http://mozilla.org/MPL/2.0/.
#include "GL/glew.h"
#include "ResourceManager.h"
#include "Segment.h"
#include "Texture.h"
#include "material.h"
typedef enum
{
@@ -142,8 +142,8 @@ private:
/*
GLuint DisplayListID = 0;
*/
texture_handle TextureID1 = 0; // tekstura szyn albo nawierzchni
texture_handle TextureID2 = 0; // tekstura automatycznej podsypki albo pobocza
material_handle m_material1 = 0; // tekstura szyn albo nawierzchni
material_handle m_material2 = 0; // tekstura automatycznej podsypki albo pobocza
typedef std::vector<geometry_handle> geometryhandle_sequence;
geometryhandle_sequence Geometry1; // geometry chunks textured with texture 1
geometryhandle_sequence Geometry2; // geometry chunks textured with texture 2
@@ -257,8 +257,8 @@ public:
GLuint TextureGet(int i) {
return (
i ?
TextureID1 :
TextureID2 ); };
m_material1 :
m_material2 ); };
bool IsGroupable();
int TestPoint(vector3 *Point);
void MovedUp1(float const dh);

View File

@@ -225,6 +225,9 @@
<ClCompile Include="translation.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="material.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Globals.h">
@@ -440,6 +443,9 @@
<ClInclude Include="translation.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="material.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="maszyna.rc">

143
material.cpp Normal file
View File

@@ -0,0 +1,143 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "material.h"
#include "renderer.h"
#include "usefull.h"
#include "globals.h"
bool
opengl_material::deserialize( cParser &Input, bool const Loadnow ) {
bool result { false };
while( true == deserialize_mapping( Input, Loadnow ) ) {
result = true; // once would suffice but, eh
}
has_alpha = (
texture1 != NULL ?
GfxRenderer.Texture( texture1 ).has_alpha :
false );
return result;
}
// imports member data pair from the config file
bool
opengl_material::deserialize_mapping( cParser &Input, bool const Loadnow ) {
if( false == Input.getTokens( 2, true, "\n\r\t;, " ) ) {
return false;
}
std::string path;
if( name.rfind( '\\' ) != std::string::npos ) {
path = name.substr( 0, name.rfind( '\\' ) + 1 );
}
std::string key, value;
Input
>> key
>> value;
if( key == "texture1:" ) { texture1 = GfxRenderer.Fetch_Texture( path + value, Loadnow ); }
else if( key == "texture2:" ) { texture2 = GfxRenderer.Fetch_Texture( path + value, Loadnow ); }
return true; // return value marks a key: value pair was extracted, nothing about whether it's recognized
}
// create material object from data stored in specified file.
// NOTE: the deferred load parameter is passed to textures defined by material, the material itself is always loaded immediately
material_handle
material_manager::create( std::string const &Filename, bool const Loadnow ) {
auto filename { Filename };
if( filename.find( '|' ) != std::string::npos )
filename.erase( filename.find( '|' ) ); // po | może być nazwa kolejnej tekstury
if( filename.rfind( '.' ) != std::string::npos ) {
// we can get extension for .mat or, in legacy files, some image format. just trim it and set it to material file extension
filename.erase( filename.rfind( '.' ) );
}
filename += ".mat";
for( char &c : filename ) {
// change forward slashes to windows ones. NOTE: probably not strictly necessary, but eh
c = ( c == '/' ? '\\' : c );
}
if( filename.find( '\\' ) == std::string::npos ) {
// jeśli bieżaca ścieżka do tekstur nie została dodana to dodajemy domyślną
filename = szTexturePath + filename;
}
// try to locate requested material in the databank
auto const databanklookup = find_in_databank( filename );
if( databanklookup != npos ) {
return databanklookup;
}
// if this fails, try to look for it on disk
opengl_material material;
material.name = filename;
auto const disklookup = find_on_disk( filename );
if( disklookup != "" ) {
cParser materialparser( disklookup, cParser::buffer_FILE );
if( false == material.deserialize( materialparser, Loadnow ) ) {
// deserialization failed but the .mat file does exist, so we give up at this point
return NULL;
}
}
else {
// if there's no .mat file, this could be legacy method of referring just to diffuse texture directly, make a material out of it in such case
material.texture1 = GfxRenderer.Fetch_Texture( Filename, Loadnow );
if( material.texture1 == NULL ) {
// if there's also no texture, give up
return NULL;
}
material.has_alpha = GfxRenderer.Texture( material.texture1 ).has_alpha;
}
material_handle handle = m_materials.size();
m_materials.emplace_back( material );
m_materialmappings.emplace( material.name, handle );
return handle;
};
// checks whether specified texture is in the texture bank. returns texture id, or npos.
material_handle
material_manager::find_in_databank( std::string const &Materialname ) const {
auto lookup = m_materialmappings.find( Materialname );
if( lookup != m_materialmappings.end() ) {
return lookup->second;
}
// jeszcze próba z dodatkową ścieżką
lookup = m_materialmappings.find( szTexturePath + Materialname );
return (
lookup != m_materialmappings.end() ?
lookup->second :
npos );
}
// checks whether specified file exists.
// NOTE: this is direct copy of the method used by texture manager. TBD, TODO: refactor into common routine?
std::string
material_manager::find_on_disk( std::string const &Materialname ) const {
return(
FileExists( Materialname ) ? Materialname :
FileExists( szTexturePath + Materialname ) ? szTexturePath + Materialname :
"" );
}
//---------------------------------------------------------------------------

64
material.h Normal file
View File

@@ -0,0 +1,64 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "texture.h"
#include "parser.h"
typedef int material_handle;
// a collection of parameters for the rendering setup.
// for modern opengl this translates to set of attributes for the active shaders,
// for legacy opengl this is basically just texture(s) assigned to geometry
struct opengl_material {
texture_handle texture1 { NULL }; // primary texture, typically diffuse+apha
texture_handle texture2 { NULL }; // secondary texture, typically normal+reflection
bool has_alpha { false }; // alpha state, calculated from presence of alpha in texture1
std::string name;
// methods:
bool
deserialize( cParser &Input, bool const Loadnow );
private:
// imports member data pair from the config file
bool
deserialize_mapping( cParser &Input, bool const Loadnow );
};
class material_manager {
public:
material_manager() { m_materials.emplace_back( opengl_material() ); } // empty bindings for null material
material_handle
create( std::string const &Filename, bool const Loadnow );
opengl_material const &
material( material_handle const Material ) const { return m_materials[ Material ]; }
private:
// types
typedef std::vector<opengl_material> material_sequence;
typedef std::unordered_map<std::string, std::size_t> index_map;
// methods:
// checks whether specified texture is in the texture bank. returns texture id, or npos.
material_handle
find_in_databank( std::string const &Materialname ) const;
// checks whether specified file exists. returns name of the located file, or empty string.
std::string
find_on_disk( std::string const &Materialname ) const;
// members:
material_handle const npos { -1 };
material_sequence m_materials;
index_map m_materialmappings;
};
//---------------------------------------------------------------------------

View File

@@ -120,6 +120,7 @@ geometry_bank::vertices( geometry_handle const &Geometry ) const {
GLuint opengl_vbogeometrybank::m_activebuffer { NULL }; // buffer bound currently on the opengl end, if any
unsigned int opengl_vbogeometrybank::m_activestreams { stream::none }; // currently enabled data type pointers
std::vector<GLint> opengl_vbogeometrybank::m_activetexturearrays; // currently enabled texture coord arrays
// create() subclass details
void
@@ -274,12 +275,19 @@ opengl_vbogeometrybank::bind_streams( stream_units const &Units, unsigned int co
::glDisableClientState( GL_COLOR_ARRAY );
}
if( Streams & stream::texture ) {
::glClientActiveTexture( Units.texture );
::glTexCoordPointer( 2, GL_FLOAT, sizeof( basic_vertex ), static_cast<char *>( nullptr ) + 24 );
::glEnableClientState( GL_TEXTURE_COORD_ARRAY );
for( auto unit : Units.texture ) {
::glClientActiveTexture( unit );
::glTexCoordPointer( 2, GL_FLOAT, sizeof( basic_vertex ), static_cast<char *>( nullptr ) + 24 );
::glEnableClientState( GL_TEXTURE_COORD_ARRAY );
}
m_activetexturearrays = Units.texture;
}
else {
::glDisableClientState( GL_TEXTURE_COORD_ARRAY );
for( auto unit : Units.texture ) {
::glClientActiveTexture( unit );
::glDisableClientState( GL_TEXTURE_COORD_ARRAY );
}
m_activetexturearrays.clear(); // NOTE: we're simplifying here, since we always toggle the same texture coord sets
}
m_activestreams = Streams;
@@ -291,9 +299,13 @@ opengl_vbogeometrybank::release_streams() {
::glDisableClientState( GL_VERTEX_ARRAY );
::glDisableClientState( GL_NORMAL_ARRAY );
::glDisableClientState( GL_COLOR_ARRAY );
::glDisableClientState( GL_TEXTURE_COORD_ARRAY );
for( auto unit : m_activetexturearrays ) {
::glClientActiveTexture( unit );
::glDisableClientState( GL_TEXTURE_COORD_ARRAY );
}
m_activestreams = stream::none;
m_activetexturearrays.clear();
}
// opengl display list based variant of the geometry bank
@@ -331,7 +343,7 @@ opengl_dlgeometrybank::draw_( geometry_handle const &Geometry, stream_units cons
for( auto const &vertex : chunk.vertices ) {
if( Streams & stream::normal ) { ::glNormal3fv( glm::value_ptr( vertex.normal ) ); }
else if( Streams & stream::color ) { ::glColor3fv( glm::value_ptr( vertex.normal ) ); }
if( Streams & stream::texture ) { ::glMultiTexCoord2fv( Units.texture, glm::value_ptr( vertex.texture ) ); }
if( Streams & stream::texture ) { for( auto unit : Units.texture ) { ::glMultiTexCoord2fv( unit, glm::value_ptr( vertex.texture ) ); } }
if( Streams & stream::position ) { ::glVertex3fv( glm::value_ptr( vertex.position ) ); }
}
::glEnd();

View File

@@ -46,7 +46,7 @@ unsigned int const color_streams { stream::position | stream::color | stream::te
struct stream_units {
GLint texture { GL_TEXTURE0 }; // unit associated with main texture data stream. TODO: allow multiple units per stream
std::vector<GLint> texture { GL_TEXTURE0 }; // unit associated with main texture data stream. TODO: allow multiple units per stream
};
typedef std::vector<basic_vertex> vertex_array;
@@ -207,6 +207,7 @@ private:
// members:
static GLuint m_activebuffer; // buffer bound currently on the opengl end, if any
static unsigned int m_activestreams;
static std::vector<GLint> m_activetexturearrays;
GLuint m_buffer { NULL }; // id of the buffer holding data on the opengl end
std::size_t m_buffercapacity{ 0 }; // total capacity of the last established buffer
chunkrecord_sequence m_chunkrecords; // helper data for all stored geometry chunks, in matching order

View File

@@ -98,9 +98,10 @@ opengl_renderer::Init( GLFWwindow *Window ) {
glEnable( GL_CULL_FACE ); // Cull back-facing triangles
glShadeModel( GL_SMOOTH ); // Enable Smooth Shading
glActiveTexture( m_diffusetextureunit );
m_geometry.units().texture = m_diffusetextureunit;
m_geometry.units().texture = std::vector<GLint>{ m_normaltextureunit, m_diffusetextureunit };
m_textures.assign_units( m_helpertextureunit, m_shadowtextureunit, m_normaltextureunit, m_diffusetextureunit ); // TODO: add reflections unit
UILayer.set_unit( m_diffusetextureunit );
Active_Texture( m_diffusetextureunit );
::glDepthFunc( GL_LEQUAL );
glEnable( GL_DEPTH_TEST );
@@ -215,7 +216,7 @@ opengl_renderer::Init( GLFWwindow *Window ) {
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE );
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
::glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE );
::glBindTexture( GL_TEXTURE_2D, 0 );
::glBindTexture( GL_TEXTURE_2D, NULL );
#ifdef EU07_USE_DEBUG_SHADOWMAP
::glGenTextures( 1, &m_shadowdebugtexture );
::glBindTexture( GL_TEXTURE_2D, m_shadowdebugtexture );
@@ -577,24 +578,12 @@ opengl_renderer::setup_pass( renderpass_config &Config, rendermode const Mode, f
case rendermode::pickscenery: {
// TODO: scissor test for pick modes
// projection
if( true == m_framebuffersupport ) {
auto const angle = Global::FieldOfView / Global::ZoomFactor;
auto const height = std::max( 1.0f, (float)Global::iWindowWidth ) / std::max( 1.0f, (float)Global::iWindowHeight ) / ( Global::iWindowWidth / EU07_PICKBUFFERSIZE );
camera.projection() *=
glm::perspective(
glm::radians( Global::FieldOfView / Global::ZoomFactor ),
std::max( 1.f, (float)Global::iWindowWidth ) / std::max( 1.0f, (float)Global::iWindowHeight ) / ( Global::iWindowWidth / EU07_PICKBUFFERSIZE ),
0.1f * Global::ZoomFactor,
Config.draw_range * Global::fDistanceFactor );
}
else {
camera.projection() *=
glm::perspective(
glm::radians( Global::FieldOfView / Global::ZoomFactor ),
std::max( 1.f, (float)Global::iWindowWidth ) / std::max( 1.f, (float)Global::iWindowHeight ),
0.1f * Global::ZoomFactor,
Config.draw_range * Global::fDistanceFactor );
}
camera.projection() *=
glm::perspective(
glm::radians( Global::FieldOfView / Global::ZoomFactor ),
std::max( 1.f, (float)Global::iWindowWidth ) / std::max( 1.f, (float)Global::iWindowHeight ),
0.1f * Global::ZoomFactor,
Config.draw_range * Global::fDistanceFactor );
// modelview
camera.position() = Global::pCameraPosition;
World.Camera.SetMatrix( viewmatrix );
@@ -674,17 +663,20 @@ opengl_renderer::setup_units( bool const Diffuse, bool const Shadows, bool const
// helper texture unit.
// darkens previous stage, preparing data for the shadow texture unit to select from
if( m_helpertextureunit >= 0 ) {
if( ( true == Global::RenderShadows ) && ( true == Shadows ) ) {
// setup reflection texture unit
::glActiveTexture( m_helpertextureunit );
Bind( m_reflectiontexture ); // TBD, TODO: move to reflection unit setup
Active_Texture( m_helpertextureunit );
if( ( true == Reflections )
|| ( ( true == Global::RenderShadows ) && ( true == Shadows ) ) ) {
m_textures.bind( textureunit::helper, m_reflectiontexture );
::glEnable( GL_TEXTURE_2D );
/*
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
glEnable( GL_TEXTURE_GEN_S );
glEnable( GL_TEXTURE_GEN_T );
*/
}
else {
::glDisable( GL_TEXTURE_2D );
}
if( ( true == Global::RenderShadows ) && ( true == Shadows ) ) {
::glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
::glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, glm::value_ptr( m_shadowcolor ) ); // TODO: dynamically calculated shadow colour, based on sun height
@@ -698,14 +690,24 @@ opengl_renderer::setup_units( bool const Diffuse, bool const Shadows, bool const
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS );
}
else {
::glActiveTexture( m_helpertextureunit );
::glDisable( GL_TEXTURE_2D );
/*
::glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE ); // pass the previous stage colour down the chain
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE ); // pass the previous stage alpha down the chain
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS );
}
if( true == Reflections ) {
::glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
::glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
::glEnable( GL_TEXTURE_GEN_S );
::glEnable( GL_TEXTURE_GEN_T );
}
else {
::glDisable( GL_TEXTURE_GEN_S );
::glDisable( GL_TEXTURE_GEN_T );
::glDisable( GL_TEXTURE_GEN_R );
::glDisable( GL_TEXTURE_GEN_Q );
*/
}
}
// shadow texture unit.
@@ -715,7 +717,8 @@ opengl_renderer::setup_units( bool const Diffuse, bool const Shadows, bool const
&& ( true == Shadows )
&& ( m_shadowcolor != colors::white ) ) {
::glActiveTexture( m_shadowtextureunit );
Active_Texture( m_shadowtextureunit );
// NOTE: shadowmap isn't part of regular texture system, so we use direct bind call here
::glBindTexture( GL_TEXTURE_2D, m_shadowtexture );
::glEnable( GL_TEXTURE_2D );
// s
@@ -745,7 +748,7 @@ opengl_renderer::setup_units( bool const Diffuse, bool const Shadows, bool const
}
else {
// turn off shadow map tests
::glActiveTexture( m_shadowtextureunit );
Active_Texture( m_shadowtextureunit );
::glDisable( GL_TEXTURE_2D );
::glDisable( GL_TEXTURE_GEN_S );
@@ -754,9 +757,35 @@ opengl_renderer::setup_units( bool const Diffuse, bool const Shadows, bool const
::glDisable( GL_TEXTURE_GEN_Q );
}
}
// reflections/normals texture unit
// NOTE: comes after diffuse stage in the operation chain
if( m_normaltextureunit >= 0 ) {
Active_Texture( m_normaltextureunit );
if( true == Reflections ) {
::glEnable( GL_TEXTURE_2D );
::glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE ); // blend between object colour and env.reflection
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0 );
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS );
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE ); // alpha channel of the normal map controls reflection strength
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA );
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE ); // pass the previous stage alpha down the chain
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS );
}
else {
::glDisable( GL_TEXTURE_2D );
}
}
// diffuse texture unit.
// NOTE: diffuse texture mapping is never fully disabled, alpha channel information is always included
::glActiveTexture( m_diffusetextureunit );
Active_Texture( m_diffusetextureunit );
::glEnable( GL_TEXTURE_2D );
if( true == Diffuse ) {
// default behaviour, modulate with previous stage
::glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
@@ -788,14 +817,15 @@ void
opengl_renderer::switch_units( bool const Diffuse, bool const Shadows, bool const Reflections ) {
// helper texture unit.
if( m_helpertextureunit >= 0 ) {
if( ( true == Global::RenderShadows )
&& ( true == Shadows )
&& ( m_shadowcolor != colors::white ) ) {
::glActiveTexture( m_helpertextureunit );
if( ( true == Reflections )
|| ( ( true == Global::RenderShadows )
&& ( true == Shadows )
&& ( m_shadowcolor != colors::white ) ) ) {
Active_Texture( m_helpertextureunit );
::glEnable( GL_TEXTURE_2D );
}
else {
::glActiveTexture( m_helpertextureunit );
Active_Texture( m_helpertextureunit );
::glDisable( GL_TEXTURE_2D );
}
}
@@ -803,25 +833,35 @@ opengl_renderer::switch_units( bool const Diffuse, bool const Shadows, bool cons
if( m_shadowtextureunit >= 0 ) {
if( ( true == Global::RenderShadows ) && ( true == Shadows ) ) {
::glActiveTexture( m_shadowtextureunit );
Active_Texture( m_shadowtextureunit );
::glEnable( GL_TEXTURE_2D );
}
else {
::glActiveTexture( m_shadowtextureunit );
Active_Texture( m_shadowtextureunit );
::glDisable( GL_TEXTURE_2D );
}
}
// normal/reflection texture unit
if( true == Reflections ) {
Active_Texture( m_normaltextureunit );
::glEnable( GL_TEXTURE_2D );
}
else {
Active_Texture( m_normaltextureunit );
::glDisable( GL_TEXTURE_2D );
}
// diffuse texture unit.
// NOTE: toggle actually disables diffuse texture mapping, unlike setup counterpart
if( true == Diffuse ) {
::glActiveTexture( m_diffusetextureunit );
Active_Texture( m_diffusetextureunit );
::glEnable( GL_TEXTURE_2D );
}
else {
::glActiveTexture( m_diffusetextureunit );
Active_Texture( m_diffusetextureunit );
::glDisable( GL_TEXTURE_2D );
}
}
@@ -829,10 +869,9 @@ opengl_renderer::switch_units( bool const Diffuse, bool const Shadows, bool cons
void
opengl_renderer::setup_shadow_color( glm::vec4 const &Shadowcolor ) {
::glActiveTexture( m_helpertextureunit );
Active_Texture( m_helpertextureunit );
::glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, glm::value_ptr( Shadowcolor ) ); // in-shadow colour multiplier
::glActiveTexture( m_diffusetextureunit );
Active_Texture( m_diffusetextureunit );
}
bool
@@ -854,7 +893,7 @@ opengl_renderer::Render( world_environment *Environment ) {
return false;
}
Bind( NULL );
Bind_Material( NULL );
::glDisable( GL_LIGHTING );
::glDisable( GL_DEPTH_TEST );
::glDepthMask( GL_FALSE );
@@ -903,7 +942,7 @@ opengl_renderer::Render( world_environment *Environment ) {
auto const &modelview = OpenGLMatrices.data( GL_MODELVIEW );
// sun
{
Bind( m_suntexture );
Bind_Texture( m_suntexture );
::glColor4f( suncolor.x, suncolor.y, suncolor.z, 1.0f );
auto const sunvector = Environment->m_sun.getDirection();
auto const sunposition = modelview * glm::vec4( sunvector.x, sunvector.y, sunvector.z, 1.0f );
@@ -924,7 +963,7 @@ opengl_renderer::Render( world_environment *Environment ) {
}
// moon
{
Bind( m_moontexture );
Bind_Texture( m_moontexture );
glm::vec3 mooncolor( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f );
::glColor4f( mooncolor.x, mooncolor.y, mooncolor.z, static_cast<GLfloat>( 1.0 - Global::fLuminance * 0.5 ) );
@@ -1032,21 +1071,48 @@ opengl_renderer::Vertices( geometry_handle const &Geometry ) const {
return m_geometry.vertices( Geometry );
}
// texture methods
texture_handle
opengl_renderer::Fetch_Texture( std::string const &Filename, std::string const &Dir, int const Filter, bool const Loadnow ) {
// material methods
material_handle
opengl_renderer::Fetch_Material( std::string const &Filename, bool const Loadnow ) {
return m_textures.create( Filename, Dir, Filter, Loadnow );
return m_materials.create( Filename, Loadnow );
}
void
opengl_renderer::Bind( texture_handle const Texture ) {
// temporary until we separate the renderer
m_textures.bind( Texture );
opengl_renderer::Bind_Material( material_handle const Material ) {
auto const &material = m_materials.material( Material );
m_textures.bind( textureunit::normals, material.texture2 );
m_textures.bind( textureunit::diffuse, material.texture1 );
}
opengl_material const &
opengl_renderer::Material( material_handle const Material ) const {
return m_materials.material( Material );
}
// texture methods
void
opengl_renderer::Active_Texture( GLint const Textureunit ) {
return m_textures.unit( Textureunit );
}
texture_handle
opengl_renderer::Fetch_Texture( std::string const &Filename, bool const Loadnow ) {
return m_textures.create( Filename, Loadnow );
}
void
opengl_renderer::Bind_Texture( texture_handle const Texture ) {
m_textures.bind( textureunit::diffuse, Texture );
}
opengl_texture const &
opengl_renderer::Texture( texture_handle const Texture ) {
opengl_renderer::Texture( texture_handle const Texture ) const {
return m_textures.texture( Texture );
}
@@ -1431,7 +1497,7 @@ opengl_renderer::Render( TGroundNode *Node ) {
::glLineWidth( static_cast<float>( linewidth ) );
}
GfxRenderer.Bind( NULL );
GfxRenderer.Bind_Material( NULL );
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
@@ -1464,7 +1530,7 @@ opengl_renderer::Render( TGroundNode *Node ) {
return false;
}
// setup
Bind( Node->TextureID );
Bind_Material( Node->m_material );
switch( m_renderpass.draw_mode ) {
case rendermode::color: {
::glColor3fv( glm::value_ptr( Node->Diffuse ) );
@@ -1784,12 +1850,12 @@ opengl_renderer::Render( TSubModel *Submodel ) {
#endif
// material configuration:
// textures...
if( Submodel->TextureID < 0 ) { // zmienialne skóry
Bind( Submodel->ReplacableSkinId[ -Submodel->TextureID ] );
if( Submodel->m_material < 0 ) { // zmienialne skóry
Bind_Material( Submodel->ReplacableSkinId[ -Submodel->m_material ] );
}
else {
// również 0
Bind( Submodel->TextureID );
Bind_Material( Submodel->m_material );
}
// ...colors...
::glColor3fv( glm::value_ptr( Submodel->f4Diffuse ) ); // McZapkie-240702: zamiast ub
@@ -1839,12 +1905,12 @@ opengl_renderer::Render( TSubModel *Submodel ) {
// scenery picking and shadow both use enforced colour and no frills
// material configuration:
// textures...
if( Submodel->TextureID < 0 ) { // zmienialne skóry
Bind( Submodel->ReplacableSkinId[ -Submodel->TextureID ] );
if( Submodel->m_material < 0 ) { // zmienialne skóry
Bind_Material( Submodel->ReplacableSkinId[ -Submodel->m_material ] );
}
else {
// również 0
Bind( Submodel->TextureID );
Bind_Material( Submodel->m_material );
}
// main draw call
m_geometry.draw( Submodel->m_geometry );
@@ -1857,12 +1923,12 @@ opengl_renderer::Render( TSubModel *Submodel ) {
m_pickcontrolsitems.emplace_back( Submodel );
::glColor3fv( glm::value_ptr( pick_color( m_pickcontrolsitems.size() ) ) );
// textures...
if( Submodel->TextureID < 0 ) { // zmienialne skóry
Bind( Submodel->ReplacableSkinId[ -Submodel->TextureID ] );
if( Submodel->m_material < 0 ) { // zmienialne skóry
Bind_Material( Submodel->ReplacableSkinId[ -Submodel->m_material ] );
}
else {
// również 0
Bind( Submodel->TextureID );
Bind_Material( Submodel->m_material );
}
// main draw call
m_geometry.draw( Submodel->m_geometry );
@@ -1902,7 +1968,7 @@ opengl_renderer::Render( TSubModel *Submodel ) {
// material configuration:
::glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_POINT_BIT );
Bind( NULL );
Bind_Material( NULL );
::glPointSize( std::max( 3.f, 5.f * distancefactor * anglefactor ) );
::glColor4f( Submodel->f4Diffuse[ 0 ], Submodel->f4Diffuse[ 1 ], Submodel->f4Diffuse[ 2 ], lightlevel * anglefactor );
::glDisable( GL_LIGHTING );
@@ -1941,7 +2007,7 @@ opengl_renderer::Render( TSubModel *Submodel ) {
// material configuration:
::glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT );
Bind( NULL );
Bind_Material( NULL );
::glDisable( GL_LIGHTING );
// main draw call
@@ -1976,20 +2042,20 @@ opengl_renderer::Render( TSubModel *Submodel ) {
void
opengl_renderer::Render( TTrack *Track ) {
if( ( Track->TextureID1 == 0 )
&& ( Track->TextureID2 == 0 ) ) {
if( ( Track->m_material1 == 0 )
&& ( Track->m_material2 == 0 ) ) {
return;
}
switch( m_renderpass.draw_mode ) {
case rendermode::color: {
Track->EnvironmentSet();
if( Track->TextureID1 != 0 ) {
Bind( Track->TextureID1 );
if( Track->m_material1 != 0 ) {
Bind_Material( Track->m_material1 );
m_geometry.draw( std::begin( Track->Geometry1 ), std::end( Track->Geometry1 ) );
}
if( Track->TextureID2 != 0 ) {
Bind( Track->TextureID2 );
if( Track->m_material2 != 0 ) {
Bind_Material( Track->m_material2 );
m_geometry.draw( std::begin( Track->Geometry2 ), std::end( Track->Geometry2 ) );
}
Track->EnvironmentReset();
@@ -1997,12 +2063,12 @@ opengl_renderer::Render( TTrack *Track ) {
}
case rendermode::pickscenery:
case rendermode::shadows: {
if( Track->TextureID1 != 0 ) {
Bind( Track->TextureID1 );
if( Track->m_material1 != 0 ) {
Bind_Material( Track->m_material1 );
m_geometry.draw( std::begin( Track->Geometry1 ), std::end( Track->Geometry1 ) );
}
if( Track->TextureID2 != 0 ) {
Bind( Track->TextureID2 );
if( Track->m_material2 != 0 ) {
Bind_Material( Track->m_material2 );
m_geometry.draw( std::begin( Track->Geometry2 ), std::end( Track->Geometry2 ) );
}
break;
@@ -2141,7 +2207,7 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
auto const color { Node->hvTraction->wire_color() };
::glColor4f( color.r, color.g, color.b, linealpha );
Bind( NULL );
Bind_Material( NULL );
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
@@ -2217,7 +2283,7 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
::glLineWidth( static_cast<float>(linewidth) );
}
GfxRenderer.Bind( NULL );
GfxRenderer.Bind_Material( NULL );
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
@@ -2242,7 +2308,7 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
// setup
::glColor3fv( glm::value_ptr( Node->Diffuse ) );
Bind( Node->TextureID );
Bind_Material( Node->m_material );
::glPushMatrix();
auto const originoffset = Node->m_rootposition - m_renderpass.camera.position();
@@ -2423,12 +2489,12 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
}
#endif
// textures...
if( Submodel->TextureID < 0 ) { // zmienialne skóry
Bind( Submodel->ReplacableSkinId[ -Submodel->TextureID ] );
if( Submodel->m_material < 0 ) { // zmienialne skóry
Bind_Material( Submodel->ReplacableSkinId[ -Submodel->m_material ] );
}
else {
// również 0
Bind( Submodel->TextureID );
Bind_Material( Submodel->m_material );
}
// ...colors...
::glColor3fv( glm::value_ptr(Submodel->f4Diffuse) ); // McZapkie-240702: zamiast ub
@@ -2495,7 +2561,7 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
// setup
::glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT );
Bind( m_glaretexture );
Bind_Texture( m_glaretexture );
::glColor4f( Submodel->f4Diffuse[ 0 ], Submodel->f4Diffuse[ 1 ], Submodel->f4Diffuse[ 2 ], glarelevel );
::glDisable( GL_LIGHTING );
::glBlendFunc( GL_SRC_ALPHA, GL_ONE );
@@ -2585,9 +2651,8 @@ opengl_renderer::Update_Pick_Control() {
if( true == m_framebuffersupport ) {
// ::glReadBuffer( GL_COLOR_ATTACHMENT0_EXT );
pickbufferpos = glm::ivec2{
mousepos.x * EU07_PICKBUFFERSIZE / Global::iWindowWidth,
mousepos.y * EU07_PICKBUFFERSIZE / Global::iWindowHeight
};
mousepos.x * EU07_PICKBUFFERSIZE / std::max( 1, Global::iWindowWidth ),
mousepos.y * EU07_PICKBUFFERSIZE / std::max( 1, Global::iWindowHeight ) };
}
else {
// ::glReadBuffer( GL_BACK );

View File

@@ -11,7 +11,7 @@ http://mozilla.org/MPL/2.0/.
#include "GL/glew.h"
#include "openglgeometrybank.h"
#include "texture.h"
#include "material.h"
#include "lightarray.h"
#include "dumb3d.h"
#include "frustum.h"
@@ -73,13 +73,6 @@ struct opengl_technique {
};
// a collection of parameters for the rendering setup.
// for modern opengl this translates to set of attributes for the active shaders,
// for legacy opengl this is basically just texture(s) assigned to geometry
struct opengl_material {
};
// simple camera object. paired with 'virtual camera' in the scene
class opengl_camera {
@@ -175,13 +168,22 @@ public:
// provides direct access to vertex data of specfied chunk
vertex_array const &
Vertices( geometry_handle const &Geometry ) const;
// texture methods
texture_handle
Fetch_Texture( std::string const &Filename, std::string const &Dir = szTexturePath, int const Filter = -1, bool const Loadnow = true );
// material methods
material_handle
Fetch_Material( std::string const &Filename, bool const Loadnow = true );
void
Bind( texture_handle const Texture );
Bind_Material( material_handle const Material );
opengl_material const &
Material( material_handle const Material ) const;
// texture methods
void
Active_Texture( GLint const Textureunit );
texture_handle
Fetch_Texture( std::string const &Filename, bool const Loadnow = true );
void
Bind_Texture( texture_handle const Texture );
opengl_texture const &
Texture( texture_handle const Texture );
Texture( texture_handle const Texture ) const;
// light methods
void
Disable_Lights();
@@ -215,6 +217,13 @@ private:
pickscenery
};
enum textureunit {
helper = 0,
shadows,
normals,
diffuse
};
typedef std::pair< double, TSubRect * > distancesubcell_pair;
struct renderpass_config {
@@ -292,6 +301,7 @@ private:
// members
GLFWwindow *m_window { nullptr };
geometrybank_manager m_geometry;
material_manager m_materials;
texture_manager m_textures;
opengllight_array m_lights;
@@ -316,9 +326,10 @@ private:
#endif
glm::mat4 m_shadowtexturematrix; // conversion from camera-centric world space to light-centric clip space
int m_shadowtextureunit { GL_TEXTURE1 };
int m_helpertextureunit { GL_TEXTURE0 };
int m_diffusetextureunit { GL_TEXTURE2 };
int m_shadowtextureunit { GL_TEXTURE1 };
int m_normaltextureunit { GL_TEXTURE2 };
int m_diffusetextureunit{ GL_TEXTURE3 };
float m_drawtime { 1000.f / 30.f * 20.f }; // start with presumed 'neutral' average of 30 fps
std::chrono::steady_clock::time_point m_drawstart; // cached start time of previous frame
@@ -327,6 +338,7 @@ private:
float m_drawtimeshadowpass { 0.f };
double m_updateaccumulator { 0.0 };
std::string m_debuginfo;
std::string m_pickdebuginfo;
glm::vec4 m_baseambient { 0.0f, 0.0f, 0.0f, 1.0f };
glm::vec4 m_shadowcolor { 0.5f, 0.5f, 0.5f, 1.f };

View File

@@ -216,7 +216,7 @@ ui_layer::render_background() {
if( m_background == 0 ) return;
// NOTE: we limit/expect the background to come with 4:3 ratio.
// TODO, TBD: if we expose texture width or ratio from texture object, this limitation could be lifted
GfxRenderer.Bind( m_background );
GfxRenderer.Bind_Texture( m_background );
auto const height { 768.0f };
auto const &texture = GfxRenderer.Texture( m_background );
float const width = (
@@ -239,7 +239,7 @@ ui_layer::render_texture() {
::glColor4f( 1.f, 1.f, 1.f, 1.f );
::glDisable( GL_BLEND );
GfxRenderer.Bind( NULL );
GfxRenderer.Bind_Texture( NULL );
::glBindTexture( GL_TEXTURE_2D, m_texture );
auto const size = 512.f;
@@ -254,6 +254,8 @@ ui_layer::render_texture() {
glEnd();
::glBindTexture( GL_TEXTURE_2D, NULL );
::glEnable( GL_BLEND );
}
}

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 17
#define VERSION_MINOR 805
#define VERSION_REVISION 0
#define VERSION_MINOR 810
#define VERSION_REVISION 1