mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-19 23:49:18 +02:00
work
This commit is contained in:
@@ -434,7 +434,7 @@ bool TAnimModel::Init(std::string const &asName, std::string const &asReplacable
|
||||
m_materialdata.replacable_skins[ 1 ] = GfxRenderer.Fetch_Material( asReplacableTexture );
|
||||
}
|
||||
if( ( m_materialdata.replacable_skins[ 1 ] != null_handle )
|
||||
&& ( GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).opacity < 1.0f ) ) {
|
||||
&& ( GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).opacity == 0.0f ) ) {
|
||||
// tekstura z kanałem alfa - nie renderować w cyklu nieprzezroczystych
|
||||
m_materialdata.textures_alpha = 0x31310031;
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ set(SOURCES
|
||||
"gl/framebuffer.cpp"
|
||||
"gl/renderbuffer.cpp"
|
||||
"gl/postfx.cpp"
|
||||
"gl/cubemap.cpp"
|
||||
|
||||
"imgui/imgui.cpp"
|
||||
"imgui/imgui_demo.cpp"
|
||||
|
||||
@@ -4587,7 +4587,7 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
|
||||
else {
|
||||
m_materialdata.replacable_skins[ 1 ] = GfxRenderer.Fetch_Material( ReplacableSkin );
|
||||
}
|
||||
if( GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).opacity < 1.0f ) {
|
||||
if( GfxRenderer.Material( m_materialdata.replacable_skins[ 1 ] ).opacity == 0.0f ) {
|
||||
// tekstura -1 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
|
||||
m_materialdata.textures_alpha = 0x31310031;
|
||||
}
|
||||
@@ -4597,17 +4597,17 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
|
||||
}
|
||||
|
||||
if( ( m_materialdata.replacable_skins[ 2 ] )
|
||||
&& ( GfxRenderer.Material( m_materialdata.replacable_skins[ 2 ] ).opacity < 1.0f ) ) {
|
||||
&& ( GfxRenderer.Material( m_materialdata.replacable_skins[ 2 ] ).opacity == 0.0f ) ) {
|
||||
// tekstura -2 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
|
||||
m_materialdata.textures_alpha |= 0x02020002;
|
||||
}
|
||||
if( ( m_materialdata.replacable_skins[ 3 ] )
|
||||
&& ( GfxRenderer.Material( m_materialdata.replacable_skins[ 3 ] ).opacity < 1.0f ) ) {
|
||||
&& ( GfxRenderer.Material( m_materialdata.replacable_skins[ 3 ] ).opacity == 0.0f ) ) {
|
||||
// tekstura -3 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
|
||||
m_materialdata.textures_alpha |= 0x04040004;
|
||||
}
|
||||
if( ( m_materialdata.replacable_skins[ 4 ] )
|
||||
&& ( GfxRenderer.Material( m_materialdata.replacable_skins[ 4 ] ).opacity < 1.0f ) ) {
|
||||
&& ( GfxRenderer.Material( m_materialdata.replacable_skins[ 4 ] ).opacity == 0.0f ) ) {
|
||||
// tekstura -4 z kanałem alfa - nie renderować w cyklu nieprzezroczystych
|
||||
m_materialdata.textures_alpha |= 0x08080008;
|
||||
}
|
||||
|
||||
21
Model3d.cpp
21
Model3d.cpp
@@ -309,27 +309,27 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
else if (material.find("replacableskin") != material.npos)
|
||||
{ // McZapkie-060702: zmienialne skory modelu
|
||||
m_material = -1;
|
||||
iFlags |= (Opacity < 1.0) ? 1 : 0x10; // zmienna tekstura 1
|
||||
iFlags |= (Opacity == 1.0f) ? 1 : 0x10; // zmienna tekstura 1
|
||||
}
|
||||
else if (material == "-1")
|
||||
{
|
||||
m_material = -1;
|
||||
iFlags |= (Opacity < 1.0) ? 1 : 0x10; // zmienna tekstura 1
|
||||
iFlags |= (Opacity == 1.0f) ? 1 : 0x10; // zmienna tekstura 1
|
||||
}
|
||||
else if (material == "-2")
|
||||
{
|
||||
m_material = -2;
|
||||
iFlags |= (Opacity < 1.0) ? 2 : 0x10; // zmienna tekstura 2
|
||||
iFlags |= (Opacity == 1.0f) ? 2 : 0x10; // zmienna tekstura 2
|
||||
}
|
||||
else if (material == "-3")
|
||||
{
|
||||
m_material = -3;
|
||||
iFlags |= (Opacity < 1.0) ? 4 : 0x10; // zmienna tekstura 3
|
||||
iFlags |= (Opacity == 1.0f) ? 4 : 0x10; // zmienna tekstura 3
|
||||
}
|
||||
else if (material == "-4")
|
||||
{
|
||||
m_material = -4;
|
||||
iFlags |= (Opacity < 1.0) ? 8 : 0x10; // zmienna tekstura 4
|
||||
iFlags |= (Opacity == 1.0f) ? 8 : 0x10; // zmienna tekstura 4
|
||||
}
|
||||
else {
|
||||
Name_Material(material);
|
||||
@@ -344,13 +344,18 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
||||
// 1. Opacity=0 (przejściowo <1, czy tam <100) oraz
|
||||
// 2. tekstura ma przezroczystość
|
||||
iFlags |=
|
||||
( ( ( Opacity < 1.0 )
|
||||
( ( ( Opacity == 0.0f )
|
||||
&& ( ( m_material != null_handle )
|
||||
&& ( GfxRenderer.Material( m_material ).opacity < 1.0f ) ) ) ?
|
||||
&& ( GfxRenderer.Material( m_material ).opacity == 0.0f ) ) ) ?
|
||||
0x20 :
|
||||
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
|
||||
};
|
||||
}
|
||||
else if (eType == TP_STARS)
|
||||
{
|
||||
m_material = GfxRenderer.Fetch_Material( "stars" );
|
||||
iFlags |= 0x10;
|
||||
}
|
||||
else
|
||||
iFlags |= 0x10;
|
||||
|
||||
@@ -1682,7 +1687,7 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
|
||||
// texture-alpha based fallback if for some reason we don't have opacity flag set yet
|
||||
iFlags |= (
|
||||
( ( m_material != null_handle )
|
||||
&& ( GfxRenderer.Material( m_material ).opacity < 1.0f ) ) ?
|
||||
&& ( GfxRenderer.Material( m_material ).opacity == 0.0f ) ) ?
|
||||
0x20 :
|
||||
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
|
||||
}
|
||||
|
||||
158
Texture.cpp
158
Texture.cpp
@@ -49,7 +49,7 @@ opengl_texture::load() {
|
||||
|
||||
if( extension == "dds" ) { load_DDS(); }
|
||||
else if( extension == "tga" ) { load_TGA(); }
|
||||
else if( extension == "png" ) { load_PNG(); }
|
||||
else if( extension == "png" ) { load_PNG(); }
|
||||
else if( extension == "bmp" ) { load_BMP(); }
|
||||
else if( extension == "tex" ) { load_TEX(); }
|
||||
else { goto fail; }
|
||||
@@ -107,8 +107,8 @@ void opengl_texture::load_PNG()
|
||||
|
||||
data.resize(PNG_IMAGE_SIZE(png));
|
||||
|
||||
png_image_finish_read(&png, nullptr,
|
||||
(void*)&data[0], -data_width * PNG_IMAGE_PIXEL_SIZE(png.format), nullptr);
|
||||
png_image_finish_read(&png, nullptr,
|
||||
(void*)&data[0], -data_width * PNG_IMAGE_PIXEL_SIZE(png.format), nullptr);
|
||||
// we're storing texture data internally with bottom-left origin
|
||||
// so use negative stride
|
||||
|
||||
@@ -277,17 +277,17 @@ opengl_texture::load_DDS() {
|
||||
{
|
||||
case FOURCC_DXT1:
|
||||
// DXT1's compression ratio is 8:1
|
||||
data_format = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
|
||||
data_format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
break;
|
||||
|
||||
case FOURCC_DXT3:
|
||||
// DXT3's compression ratio is 4:1
|
||||
data_format = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
|
||||
data_format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
break;
|
||||
|
||||
case FOURCC_DXT5:
|
||||
// DXT5's compression ratio is 4:1
|
||||
data_format = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
|
||||
data_format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -299,7 +299,7 @@ opengl_texture::load_DDS() {
|
||||
data_height = ddsd.dwHeight;
|
||||
data_mapcount = ddsd.dwMipMapCount;
|
||||
|
||||
int blockSize = ( data_format == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ? 8 : 16 );
|
||||
int blockSize = ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ? 8 : 16 );
|
||||
int offset = 0;
|
||||
|
||||
while( ( data_width > Global.iMaxTextureSize ) || ( data_height > Global.iMaxTextureSize ) ) {
|
||||
@@ -341,11 +341,11 @@ opengl_texture::load_DDS() {
|
||||
// while DDS stores it with top-left origin. we need to flip it.
|
||||
if (Global.dds_upper_origin)
|
||||
{
|
||||
char *mipmap = (char*)&data[0];
|
||||
int mapcount = data_mapcount,
|
||||
width = data_width,
|
||||
height = data_height;
|
||||
while (mapcount)
|
||||
char *mipmap = (char*)&data[0];
|
||||
int mapcount = data_mapcount,
|
||||
width = data_width,
|
||||
height = data_height;
|
||||
while (mapcount)
|
||||
{
|
||||
if (ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT1)
|
||||
flip_s3tc::flip_dxt1_image(mipmap, width, height);
|
||||
@@ -354,11 +354,11 @@ opengl_texture::load_DDS() {
|
||||
else if (ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT5)
|
||||
flip_s3tc::flip_dxt45_image(mipmap, width, height);
|
||||
|
||||
mipmap += ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 ) * blockSize;
|
||||
width = std::max( width / 2, 4 );
|
||||
height = std::max( height / 2, 4 );
|
||||
--mapcount;
|
||||
}
|
||||
mipmap += ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 ) * blockSize;
|
||||
width = std::max( width / 2, 4 );
|
||||
height = std::max( height / 2, 4 );
|
||||
--mapcount;
|
||||
}
|
||||
}
|
||||
|
||||
data_components =
|
||||
@@ -525,7 +525,7 @@ opengl_texture::load_TGA() {
|
||||
buffer[ 1 ] = buffer[ 0 ];
|
||||
buffer[ 2 ] = buffer[ 0 ];
|
||||
}
|
||||
// copy the color into the image data as many times as dictated
|
||||
// copy the color into the image data as many times as dictated
|
||||
for( int i = 0; i <= chunkheader; ++i ) {
|
||||
|
||||
( *datapointer ) = ( *bufferpointer );
|
||||
@@ -581,6 +581,78 @@ opengl_texture::bind() {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unordered_map<GLint, int> opengl_texture::precompressed_formats =
|
||||
{
|
||||
{ GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 8 },
|
||||
{ GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 16 },
|
||||
{ GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 16 },
|
||||
{ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8 },
|
||||
{ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 16 },
|
||||
{ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 16 },
|
||||
};
|
||||
|
||||
std::unordered_map<GLint, GLint> opengl_texture::drivercompressed_formats =
|
||||
{
|
||||
{ GL_SRGB_ALPHA, GL_COMPRESSED_SRGB_ALPHA },
|
||||
{ GL_SRGB, GL_COMPRESSED_SRGB },
|
||||
{ GL_RGBA, GL_COMPRESSED_RGBA },
|
||||
{ GL_RGB, GL_COMPRESSED_RGB },
|
||||
{ GL_RG, GL_COMPRESSED_RG },
|
||||
{ GL_RED, GL_COMPRESSED_RED },
|
||||
};
|
||||
|
||||
std::unordered_map<GLint, std::unordered_map<GLint, GLint>> opengl_texture::mapping =
|
||||
{
|
||||
// image have, material wants, gl internalformat
|
||||
{ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, { { GL_SRGB_ALPHA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT },
|
||||
{ GL_SRGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT },
|
||||
{ GL_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT },
|
||||
{ GL_RGB, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT },
|
||||
{ GL_RG, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT },
|
||||
{ GL_RED, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT } } },
|
||||
{ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, { { GL_SRGB_ALPHA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT },
|
||||
{ GL_SRGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT },
|
||||
{ GL_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT },
|
||||
{ GL_RGB, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT },
|
||||
{ GL_RG, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT },
|
||||
{ GL_RED, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT } } },
|
||||
{ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, { { GL_SRGB_ALPHA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT },
|
||||
{ GL_SRGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT },
|
||||
{ GL_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT },
|
||||
{ GL_RGB, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT },
|
||||
{ GL_RG, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT },
|
||||
{ GL_RED, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT } } },
|
||||
{ GL_RGBA, { { GL_SRGB_ALPHA, GL_SRGB_ALPHA },
|
||||
{ GL_SRGB, GL_SRGB },
|
||||
{ GL_RGBA, GL_RGBA },
|
||||
{ GL_RGB, GL_RGB },
|
||||
{ GL_RG, GL_RG },
|
||||
{ GL_RED, GL_RED } } },
|
||||
{ GL_RGB, { { GL_SRGB_ALPHA, GL_SRGB }, // bad
|
||||
{ GL_SRGB, GL_SRGB },
|
||||
{ GL_RGBA, GL_RGB }, // bad
|
||||
{ GL_RGB, GL_RGB },
|
||||
{ GL_RG, GL_RG },
|
||||
{ GL_RED, GL_RED } } },
|
||||
{ GL_RG, { { GL_SRGB_ALPHA, GL_SRGB }, // bad
|
||||
{ GL_SRGB, GL_SRGB }, // bad
|
||||
{ GL_RGBA, GL_RG }, // bad
|
||||
{ GL_RGB, GL_RG }, // bad
|
||||
{ GL_RG, GL_RG },
|
||||
{ GL_RED, GL_RED } } },
|
||||
{ GL_RED, { { GL_SRGB_ALPHA, GL_SRGB }, // bad
|
||||
{ GL_SRGB, GL_SRGB }, // bad
|
||||
{ GL_RGBA, GL_RED }, // bad
|
||||
{ GL_RGB, GL_RED }, // bad
|
||||
{ GL_RG, GL_RED }, // bad
|
||||
{ GL_RED, GL_RED } } },
|
||||
};
|
||||
|
||||
void opengl_texture::set_components_hint(GLint hint)
|
||||
{
|
||||
components_hint = hint;
|
||||
}
|
||||
|
||||
bool
|
||||
opengl_texture::create() {
|
||||
|
||||
@@ -618,12 +690,12 @@ opengl_texture::create() {
|
||||
{
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
if (data_components == GL_DEPTH_COMPONENT)
|
||||
{
|
||||
{
|
||||
glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, borderColor);
|
||||
}
|
||||
if (target == GL_TEXTURE_2D)
|
||||
@@ -637,21 +709,32 @@ opengl_texture::create() {
|
||||
::glTexParameteri(target, GL_TEXTURE_WRAP_T, (wrapt == true ? GL_REPEAT : GL_CLAMP_TO_EDGE));
|
||||
set_filtering();
|
||||
|
||||
// data_format and data_type specifies how image is laid out in memory
|
||||
// data_components specifies what useful channels image contains
|
||||
// components_hint specifies what format we want to load
|
||||
|
||||
// now map that mess into opengl internal format
|
||||
|
||||
GLint components = data_components;
|
||||
auto f_it = precompressed_formats.find(data_format);
|
||||
if (f_it != precompressed_formats.end())
|
||||
components = data_format;
|
||||
|
||||
GLint internal_format = mapping[components][components_hint];
|
||||
|
||||
auto blocksize_it = precompressed_formats.find(internal_format);
|
||||
|
||||
for( int maplevel = 0; maplevel < data_mapcount; ++maplevel ) {
|
||||
|
||||
if( ( data_format == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT )
|
||||
|| ( data_format == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT )
|
||||
|| ( data_format == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT ) ) {
|
||||
if (blocksize_it != precompressed_formats.end())
|
||||
{
|
||||
// compressed dds formats
|
||||
int const datablocksize =
|
||||
( data_format == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ?
|
||||
8 :
|
||||
16 );
|
||||
const int datablocksize = blocksize_it->second;
|
||||
|
||||
datasize = ( ( std::max( datawidth, 4 ) + 3 ) / 4 ) * ( ( std::max( dataheight, 4 ) + 3 ) / 4 ) * datablocksize;
|
||||
|
||||
::glCompressedTexImage2D(
|
||||
target, maplevel, data_format,
|
||||
target, maplevel, internal_format,
|
||||
datawidth, dataheight, 0,
|
||||
datasize, (GLubyte *)&data[ dataoffset ] );
|
||||
|
||||
@@ -660,10 +743,12 @@ opengl_texture::create() {
|
||||
dataheight = std::max( dataheight / 2, 1 );
|
||||
}
|
||||
else {
|
||||
GLint compressed_format = drivercompressed_formats[internal_format];
|
||||
|
||||
// uncompressed texture data. have the gfx card do the compression as it sees fit
|
||||
::glTexImage2D(
|
||||
target, 0,
|
||||
Global.compress_tex ? GL_COMPRESSED_SRGB_ALPHA : GL_SRGB_ALPHA,
|
||||
target, 0,
|
||||
Global.compress_tex ? compressed_format : internal_format,
|
||||
data_width, data_height, 0,
|
||||
data_format, data_type, (GLubyte *)&data[ 0 ] );
|
||||
}
|
||||
@@ -752,11 +837,7 @@ opengl_texture::set_filtering() const {
|
||||
// default texture mode
|
||||
::glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
::glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
|
||||
if( GLEW_EXT_texture_filter_anisotropic ) {
|
||||
// anisotropic filtering
|
||||
::glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, Global.AnisotropicFiltering );
|
||||
}
|
||||
::glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY, Global.AnisotropicFiltering );
|
||||
|
||||
bool sharpen{ false };
|
||||
for( auto const &trait : traits ) {
|
||||
@@ -821,7 +902,7 @@ texture_manager::unit( GLint const Textureunit ) {
|
||||
|
||||
// ustalenie numeru tekstury, wczytanie jeśli jeszcze takiej nie było
|
||||
texture_handle
|
||||
texture_manager::create( std::string Filename, bool const Loadnow ) {
|
||||
texture_manager::create(std::string Filename, bool const Loadnow , GLint fh) {
|
||||
|
||||
if( Filename.find( '|' ) != std::string::npos )
|
||||
Filename.erase( Filename.find( '|' ) ); // po | może być nazwa kolejnej tekstury
|
||||
@@ -863,6 +944,7 @@ texture_manager::create( std::string Filename, bool const Loadnow ) {
|
||||
traits += '#';
|
||||
}
|
||||
texture->traits = traits;
|
||||
texture->components_hint = fh;
|
||||
auto const textureindex = (texture_handle)m_textures.size();
|
||||
m_textures.emplace_back( texture, std::chrono::steady_clock::time_point() );
|
||||
m_texturemappings.emplace( disklookup.first, textureindex );
|
||||
|
||||
@@ -42,6 +42,7 @@ struct opengl_texture {
|
||||
return data_height; }
|
||||
|
||||
void alloc_rendertarget(GLint format, GLint components, GLint type, int width, int height, int samples = 1);
|
||||
void set_components_hint(GLint hint);
|
||||
|
||||
// members
|
||||
GLuint id{ (GLuint)-1 }; // associated GL resource
|
||||
@@ -50,6 +51,7 @@ struct opengl_texture {
|
||||
std::string traits; // requested texture attributes: wrapping modes etc
|
||||
std::string name; // name of the texture source file
|
||||
std::size_t size{ 0 }; // size of the texture data, in kb
|
||||
GLint components_hint; // components that material wants
|
||||
|
||||
GLenum target = GL_TEXTURE_2D;
|
||||
|
||||
@@ -81,6 +83,10 @@ private:
|
||||
std::atomic<bool> is_loaded{ false }; // indicates the texture data was loaded and can be processed
|
||||
std::atomic<bool> is_good{ false }; // indicates the texture data was retrieved without errors
|
||||
*/
|
||||
|
||||
static std::unordered_map<GLint, int> precompressed_formats;
|
||||
static std::unordered_map<GLint, GLint> drivercompressed_formats;
|
||||
static std::unordered_map<GLint, std::unordered_map<GLint, GLint>> mapping;
|
||||
};
|
||||
|
||||
typedef int texture_handle;
|
||||
@@ -96,7 +102,7 @@ public:
|
||||
unit( GLint const Textureunit );
|
||||
// creates texture object out of data stored in specified file
|
||||
texture_handle
|
||||
create( std::string Filename, bool const Loadnow = true );
|
||||
create( std::string Filename, bool const Loadnow = true, GLint format_hint = GL_SRGB_ALPHA );
|
||||
// binds specified texture to specified texture unit
|
||||
void
|
||||
bind( std::size_t const Unit, texture_handle const Texture );
|
||||
|
||||
@@ -325,15 +325,15 @@ void DecompressDXT(DDS_IMAGE_DATA lImage, const GLubyte *lCompData, GLubyte *Dat
|
||||
{
|
||||
switch (lImage.format)
|
||||
{
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
DecompressDXT1(lImage, lCompData, Data);
|
||||
break;
|
||||
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
DecompressDXT3(lImage, lCompData, Data);
|
||||
break;
|
||||
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
DecompressDXT5(lImage, lCompData, Data);
|
||||
break;
|
||||
};
|
||||
|
||||
37
gl/cubemap.cpp
Normal file
37
gl/cubemap.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "cubemap.h"
|
||||
|
||||
gl::cubemap::cubemap()
|
||||
{
|
||||
glGenTextures(1, *this);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
gl::cubemap::~cubemap()
|
||||
{
|
||||
glDeleteTextures(1, *this);
|
||||
}
|
||||
|
||||
void gl::cubemap::alloc(GLint format, int width, int height, GLenum components, GLenum type)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, *this);
|
||||
for (GLuint tgt = GL_TEXTURE_CUBE_MAP_POSITIVE_X; tgt <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; tgt++)
|
||||
glTexImage2D(tgt, 0, format, width, height, 0, components, type, nullptr);
|
||||
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
}
|
||||
|
||||
void gl::cubemap::bind(int unit)
|
||||
{
|
||||
glActiveTexture(unit);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, *this);
|
||||
}
|
||||
|
||||
void gl::cubemap::generate_mipmaps()
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, *this);
|
||||
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
}
|
||||
19
gl/cubemap.h
Normal file
19
gl/cubemap.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "object.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
// cubemap texture rendertarget
|
||||
// todo: integrate with texture system
|
||||
class cubemap : public object
|
||||
{
|
||||
public:
|
||||
cubemap();
|
||||
~cubemap();
|
||||
|
||||
void alloc(GLint format, int width, int height, GLenum components, GLenum type);
|
||||
void bind(int unit);
|
||||
void generate_mipmaps();
|
||||
};
|
||||
}
|
||||
@@ -22,12 +22,24 @@ void gl::framebuffer::attach(const opengl_texture &tex, GLenum location)
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, location, tex.target, tex.id, 0);
|
||||
}
|
||||
|
||||
void gl::framebuffer::attach(const cubemap &tex, int face, GLenum location)
|
||||
{
|
||||
bind();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, location, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, *tex, 0);
|
||||
}
|
||||
|
||||
void gl::framebuffer::attach(const renderbuffer &rb, GLenum location)
|
||||
{
|
||||
bind();
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, location, GL_RENDERBUFFER, *rb);
|
||||
}
|
||||
|
||||
void gl::framebuffer::detach(GLenum location)
|
||||
{
|
||||
bind();
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, location, GL_RENDERBUFFER, 0);
|
||||
}
|
||||
|
||||
bool gl::framebuffer::is_complete()
|
||||
{
|
||||
bind();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "bindable.h"
|
||||
#include "renderbuffer.h"
|
||||
#include "Texture.h"
|
||||
#include "cubemap.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
@@ -14,7 +15,9 @@ namespace gl
|
||||
~framebuffer();
|
||||
|
||||
void attach(const opengl_texture &tex, GLenum location);
|
||||
void attach(const cubemap &tex, int face, GLenum location);
|
||||
void attach(const renderbuffer &rb, GLenum location);
|
||||
void detach(GLenum location);
|
||||
void clear(GLbitfield mask);
|
||||
|
||||
bool is_complete();
|
||||
|
||||
@@ -50,10 +50,62 @@ void gl::shader::expand_includes(std::string &str)
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, gl::shader::components_e> gl::shader::components_mapping =
|
||||
{
|
||||
{ "R", components_e::R },
|
||||
{ "RG", components_e::RG },
|
||||
{ "RGB", components_e::RGB },
|
||||
{ "RGBA", components_e::RGBA },
|
||||
{ "sRGB", components_e::sRGB },
|
||||
{ "sRGB_A", components_e::sRGB_A }
|
||||
};
|
||||
|
||||
void gl::shader::parse_config(std::string &str)
|
||||
{
|
||||
size_t start_pos = 0;
|
||||
|
||||
std::string magic = "#texture";
|
||||
while ((start_pos = str.find(magic, start_pos)) != str.npos)
|
||||
{
|
||||
size_t fp = str.find('(', start_pos);
|
||||
size_t fe = str.find(')', start_pos);
|
||||
if (fp == str.npos || fe == str.npos)
|
||||
return;
|
||||
|
||||
std::istringstream ss(str.substr(fp + 1, fe - fp - 1));
|
||||
std::string token;
|
||||
|
||||
texture_entry conf;
|
||||
|
||||
size_t arg = 0;
|
||||
while (std::getline(ss, token, ','))
|
||||
{
|
||||
std::istringstream token_ss(token);
|
||||
if (arg == 0)
|
||||
token_ss >> conf.name;
|
||||
else if (arg == 1)
|
||||
token_ss >> conf.id;
|
||||
else if (arg == 2)
|
||||
{
|
||||
std::string comp;
|
||||
token_ss >> comp;
|
||||
conf.components = components_mapping[comp];
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
|
||||
if (arg == 3)
|
||||
texture_conf.push_back(conf);
|
||||
|
||||
str.erase(start_pos, fe - start_pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
gl::shader::shader(const std::string &filename)
|
||||
{
|
||||
std::string str = read_file(filename);
|
||||
expand_includes(str);
|
||||
parse_config(str);
|
||||
|
||||
const GLchar *cstr = str.c_str();
|
||||
|
||||
@@ -92,21 +144,12 @@ void gl::program::init()
|
||||
{
|
||||
bind();
|
||||
|
||||
int i = 0;
|
||||
GLuint loc;
|
||||
while (true)
|
||||
for (shader::texture_entry &e : texture_conf)
|
||||
{
|
||||
std::string name = "tex" + std::to_string(i + 1);
|
||||
loc = glGetUniformLocation(*this, name.c_str());
|
||||
if (loc != -1)
|
||||
glUniform1i(loc, i);
|
||||
else
|
||||
break;
|
||||
i++;
|
||||
GLuint loc = glGetUniformLocation(*this, e.name.c_str());
|
||||
glUniform1i(loc, e.id);
|
||||
}
|
||||
|
||||
//tbd: do something better
|
||||
|
||||
glUniform1i(glGetUniformLocation(*this, "shadowmap"), MAX_TEXTURES + 0);
|
||||
glUniform1i(glGetUniformLocation(*this, "envmap"), MAX_TEXTURES + 1);
|
||||
|
||||
@@ -136,6 +179,7 @@ gl::program::program(std::vector<std::reference_wrapper<const gl::shader>> shade
|
||||
|
||||
void gl::program::attach(const gl::shader &s)
|
||||
{
|
||||
std::copy(s.texture_conf.begin(), s.texture_conf.end(), std::back_inserter(texture_conf));
|
||||
glAttachShader(*this, *s);
|
||||
}
|
||||
|
||||
|
||||
24
gl/shader.h
24
gl/shader.h
@@ -15,9 +15,31 @@ namespace gl
|
||||
shader(const std::string &filename);
|
||||
~shader();
|
||||
|
||||
enum class components_e
|
||||
{
|
||||
R,
|
||||
RG,
|
||||
RGB,
|
||||
RGBA,
|
||||
sRGB,
|
||||
sRGB_A
|
||||
};
|
||||
|
||||
struct texture_entry
|
||||
{
|
||||
std::string name;
|
||||
size_t id;
|
||||
components_e components;
|
||||
};
|
||||
|
||||
std::vector<texture_entry> texture_conf;
|
||||
|
||||
private:
|
||||
void expand_includes(std::string &str);
|
||||
void parse_config(std::string &str);
|
||||
std::string read_file(const std::string &filename);
|
||||
|
||||
static std::unordered_map<std::string, components_e> components_mapping;
|
||||
};
|
||||
|
||||
class program : public object, public bindable<program>
|
||||
@@ -33,6 +55,8 @@ namespace gl
|
||||
void attach(const shader &);
|
||||
void link();
|
||||
|
||||
std::vector<shader::texture_entry> texture_conf;
|
||||
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
|
||||
19
material.cpp
19
material.cpp
@@ -117,6 +117,15 @@ opengl_material::deserialize_mapping( cParser &Input, int const Priority, bool c
|
||||
return true; // return value marks a key: value pair was extracted, nothing about whether it's recognized
|
||||
}
|
||||
|
||||
std::unordered_map<gl::shader::components_e, GLint> material_manager::components_mapping =
|
||||
{
|
||||
{ gl::shader::components_e::R, GL_RED },
|
||||
{ gl::shader::components_e::RG, GL_RG },
|
||||
{ gl::shader::components_e::RGB, GL_RGB },
|
||||
{ gl::shader::components_e::RGBA, GL_RGBA },
|
||||
{ gl::shader::components_e::sRGB, GL_SRGB },
|
||||
{ gl::shader::components_e::sRGB_A, GL_SRGB_ALPHA }
|
||||
};
|
||||
|
||||
// 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
|
||||
@@ -167,12 +176,18 @@ material_manager::create( std::string const &Filename, bool const Loadnow ) {
|
||||
if (!material.shader)
|
||||
material.shader = GfxRenderer.Fetch_Shader("default");
|
||||
|
||||
for (gl::shader::texture_entry &entry : material.shader->texture_conf)
|
||||
{
|
||||
material_handle handle = material.textures[entry.id];
|
||||
if (handle)
|
||||
GfxRenderer.Texture(handle).set_components_hint(components_mapping[entry.components]);
|
||||
}
|
||||
|
||||
if (std::isnan(material.opacity))
|
||||
{
|
||||
material.opacity = 1.0f;
|
||||
if (material.textures[0] != null_handle)
|
||||
material.opacity = GfxRenderer.Texture( material.textures[0] ).has_alpha ? 0.0f : 1.0f;
|
||||
else
|
||||
material.opacity = 1.0f;
|
||||
}
|
||||
|
||||
material_handle handle = m_materials.size();
|
||||
|
||||
@@ -61,6 +61,8 @@ public:
|
||||
create( std::string const &Filename, bool const Loadnow );
|
||||
opengl_material const &
|
||||
material( material_handle const Material ) const { return m_materials[ Material ]; }
|
||||
opengl_material &
|
||||
material( material_handle const Material ) { return m_materials[ Material ]; }
|
||||
|
||||
private:
|
||||
// types
|
||||
@@ -77,6 +79,7 @@ private:
|
||||
material_sequence m_materials;
|
||||
index_map m_materialmappings;
|
||||
|
||||
static std::unordered_map<gl::shader::components_e, GLint> components_mapping;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
306
renderer.cpp
306
renderer.cpp
@@ -212,6 +212,25 @@ bool opengl_renderer::Init(GLFWwindow *Window)
|
||||
if (!m_pick_fb->is_complete())
|
||||
return false;
|
||||
|
||||
m_env_rb = std::make_unique<gl::renderbuffer>();
|
||||
m_env_rb->alloc(GL_DEPTH_COMPONENT24, EU07_ENVIRONMENTBUFFERSIZE, EU07_ENVIRONMENTBUFFERSIZE);
|
||||
m_env_tex = std::make_unique<gl::cubemap>();
|
||||
m_env_tex->alloc(GL_RGB16F, EU07_ENVIRONMENTBUFFERSIZE, EU07_ENVIRONMENTBUFFERSIZE, GL_RGB, GL_FLOAT);
|
||||
m_empty_cubemap = std::make_unique<gl::cubemap>();
|
||||
m_empty_cubemap->alloc(GL_RGB16F, 16, 16, GL_RGB, GL_FLOAT);
|
||||
|
||||
m_env_fb = std::make_unique<gl::framebuffer>();
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
m_env_fb->attach(*m_empty_cubemap, i, GL_COLOR_ATTACHMENT0);
|
||||
m_env_fb->clear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
m_env_fb->detach(GL_COLOR_ATTACHMENT0);
|
||||
m_env_fb->attach(*m_env_rb, GL_DEPTH_ATTACHMENT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -332,17 +351,12 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
||||
glDebug("render shadowmap end");
|
||||
}
|
||||
|
||||
m_msaa_fb->bind();
|
||||
// potentially update environmental cube map
|
||||
if (Render_reflections())
|
||||
setup_pass(m_renderpass, Mode); // restore color pass settings
|
||||
setup_env_map(m_env_tex.get());
|
||||
|
||||
/*
|
||||
if( ( true == m_environmentcubetexturesupport )
|
||||
&& ( true == World.InitPerformed() ) ) {
|
||||
// potentially update environmental cube map
|
||||
if( true == Render_reflections() ) {
|
||||
setup_pass( m_renderpass, Mode ); // restore draw mode. TBD, TODO: render mode stack
|
||||
}
|
||||
}
|
||||
*/
|
||||
m_msaa_fb->bind();
|
||||
|
||||
glViewport(0, 0, Global.render_width, Global.render_height);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@@ -394,18 +408,8 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
||||
Render_cab(vehicle, true);
|
||||
}
|
||||
|
||||
/*
|
||||
if( m_environmentcubetexturesupport ) {
|
||||
// restore default texture matrix for reflections cube map
|
||||
select_unit( m_helpertextureunit );
|
||||
::glMatrixMode( GL_TEXTURE );
|
||||
::glPopMatrix();
|
||||
select_unit( m_diffusetextureunit );
|
||||
::glMatrixMode( GL_MODELVIEW );
|
||||
}
|
||||
*/
|
||||
|
||||
setup_shadow_map(nullptr, m_renderpass);
|
||||
setup_env_map(nullptr);
|
||||
|
||||
m_main_fb->clear(GL_COLOR_BUFFER_BIT);
|
||||
m_msaa_fb->blit_to(*m_main_fb.get(), Global.render_width, Global.render_height, GL_COLOR_BUFFER_BIT);
|
||||
@@ -479,8 +483,8 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
||||
scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION);
|
||||
scene_ubo->update(scene_ubs);
|
||||
|
||||
Render_cab( World.Train->Dynamic(), false );
|
||||
Render_cab( World.Train->Dynamic(), true );
|
||||
Render_cab(World.Train->Dynamic(), false);
|
||||
Render_cab(World.Train->Dynamic(), true);
|
||||
m_cabshadowpass = m_renderpass;
|
||||
|
||||
// glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
@@ -494,6 +498,42 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
||||
|
||||
case rendermode::reflections:
|
||||
{
|
||||
if (!World.InitPerformed())
|
||||
break;
|
||||
|
||||
glDebug("rendermode::reflections");
|
||||
|
||||
// NOTE: buffer attachment and viewport setup in this mode is handled by the wrapper method
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
m_env_fb->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
m_env_fb->bind();
|
||||
|
||||
setup_env_map(m_empty_cubemap.get());
|
||||
|
||||
setup_matrices();
|
||||
setup_shadow_map(nullptr, m_renderpass);
|
||||
|
||||
// render
|
||||
setup_drawing(true);
|
||||
|
||||
scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION);
|
||||
scene_ubo->update(scene_ubs);
|
||||
Render(&World.Environment);
|
||||
|
||||
// opaque parts...
|
||||
setup_drawing(false);
|
||||
setup_shadow_map(m_shadow_tex.get(), m_shadowpass);
|
||||
|
||||
scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION);
|
||||
scene_ubo->update(scene_ubs);
|
||||
Render(simulation::Region);
|
||||
|
||||
m_env_fb->unbind();
|
||||
|
||||
glDebug("rendermode::reflections end");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -556,6 +596,25 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
||||
// creates dynamic environment cubemap
|
||||
bool opengl_renderer::Render_reflections()
|
||||
{
|
||||
auto const &time = simulation::Time.data();
|
||||
auto const timestamp = time.wDay * 24 * 60 + time.wHour * 60 + time.wMinute;
|
||||
if ((timestamp - m_environmentupdatetime < 1) && (glm::length(m_renderpass.camera.position() - m_environmentupdatelocation) < 1000.0))
|
||||
{
|
||||
// run update every 5+ mins of simulation time, or at least 1km from the last location
|
||||
return false;
|
||||
}
|
||||
m_environmentupdatetime = timestamp;
|
||||
m_environmentupdatelocation = m_renderpass.camera.position();
|
||||
|
||||
glViewport(0, 0, EU07_ENVIRONMENTBUFFERSIZE, EU07_ENVIRONMENTBUFFERSIZE);
|
||||
for (m_environmentcubetextureface = 0; m_environmentcubetextureface < 6; ++m_environmentcubetextureface)
|
||||
{
|
||||
m_env_fb->attach(*m_env_tex, m_environmentcubetextureface, GL_COLOR_ATTACHMENT0);
|
||||
if (m_env_fb->is_complete())
|
||||
Render_pass(rendermode::reflections);
|
||||
}
|
||||
m_env_tex->generate_mipmaps();
|
||||
m_env_fb->detach(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -702,36 +761,26 @@ void opengl_renderer::setup_pass(renderpass_config &Config, rendermode const Mod
|
||||
|
||||
break;
|
||||
}
|
||||
case rendermode::cabshadows: {
|
||||
case rendermode::cabshadows:
|
||||
{
|
||||
// fixed size cube large enough to enclose a vehicle compartment
|
||||
// modelview
|
||||
auto const lightvector =
|
||||
glm::normalize( glm::vec3{
|
||||
m_sunlight.direction.x,
|
||||
std::min( m_sunlight.direction.y, -0.2f ),
|
||||
m_sunlight.direction.z } );
|
||||
camera.position() = Global.pCameraPosition - glm::dvec3 { lightvector };
|
||||
viewmatrix *= glm::lookAt(
|
||||
camera.position(),
|
||||
glm::dvec3 { Global.pCameraPosition },
|
||||
glm::dvec3 { 0.f, 1.f, 0.f } );
|
||||
auto const lightvector = glm::normalize(glm::vec3{m_sunlight.direction.x, std::min(m_sunlight.direction.y, -0.2f), m_sunlight.direction.z});
|
||||
camera.position() = Global.pCameraPosition - glm::dvec3{lightvector};
|
||||
viewmatrix *= glm::lookAt(camera.position(), glm::dvec3{Global.pCameraPosition}, glm::dvec3{0.f, 1.f, 0.f});
|
||||
// projection
|
||||
auto const maphalfsize { Config.draw_range * 0.5f };
|
||||
camera.projection() *=
|
||||
glm::ortho(
|
||||
-maphalfsize, maphalfsize,
|
||||
-maphalfsize, maphalfsize,
|
||||
-Config.draw_range, Config.draw_range );
|
||||
/*
|
||||
// adjust the projection to sample complete shadow map texels
|
||||
auto shadowmaptexel = glm::vec2 { camera.projection() * glm::mat4{ viewmatrix } * glm::vec4{ 0.f, 0.f, 0.f, 1.f } };
|
||||
shadowmaptexel *= ( m_shadowbuffersize / 2 ) * 0.5f;
|
||||
auto shadowmapadjustment = glm::round( shadowmaptexel ) - shadowmaptexel;
|
||||
shadowmapadjustment /= ( m_shadowbuffersize / 2 ) * 0.5f;
|
||||
camera.projection() = glm::translate( glm::mat4{ 1.f }, glm::vec3{ shadowmapadjustment, 0.f } ) * camera.projection();
|
||||
*/
|
||||
auto const maphalfsize{Config.draw_range * 0.5f};
|
||||
camera.projection() *= glm::ortho(-maphalfsize, maphalfsize, -maphalfsize, maphalfsize, -Config.draw_range, Config.draw_range);
|
||||
/*
|
||||
// adjust the projection to sample complete shadow map texels
|
||||
auto shadowmaptexel = glm::vec2 { camera.projection() * glm::mat4{ viewmatrix } * glm::vec4{ 0.f, 0.f, 0.f, 1.f } };
|
||||
shadowmaptexel *= ( m_shadowbuffersize / 2 ) * 0.5f;
|
||||
auto shadowmapadjustment = glm::round( shadowmaptexel ) - shadowmaptexel;
|
||||
shadowmapadjustment /= ( m_shadowbuffersize / 2 ) * 0.5f;
|
||||
camera.projection() = glm::translate( glm::mat4{ 1.f }, glm::vec3{ shadowmapadjustment, 0.f } ) * camera.projection();
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
case rendermode::pickcontrols:
|
||||
case rendermode::pickscenery:
|
||||
{
|
||||
@@ -743,6 +792,18 @@ void opengl_renderer::setup_pass(renderpass_config &Config, rendermode const Mod
|
||||
0.1f * Global.ZoomFactor, Config.draw_range * Global.fDistanceFactor);
|
||||
break;
|
||||
}
|
||||
case rendermode::reflections:
|
||||
{
|
||||
// modelview
|
||||
camera.position() = (((true == DebugCameraFlag) && (false == Ignoredebug)) ? Global.DebugCameraPosition : Global.pCameraPosition);
|
||||
glm::dvec3 const cubefacetargetvectors[6] = {{1.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}};
|
||||
glm::dvec3 const cubefaceupvectors[6] = {{0.0, -1.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}, {0.0, -1.0, 0.0}};
|
||||
auto const cubefaceindex = m_environmentcubetextureface;
|
||||
viewmatrix *= glm::lookAt(camera.position(), camera.position() + cubefacetargetvectors[cubefaceindex], cubefaceupvectors[cubefaceindex]);
|
||||
// projection
|
||||
camera.projection() *= glm::perspective(glm::radians(90.f), 1.f, 0.1f * Global.ZoomFactor, Config.draw_range * Global.fDistanceFactor);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -754,22 +815,9 @@ void opengl_renderer::setup_pass(renderpass_config &Config, rendermode const Mod
|
||||
|
||||
void opengl_renderer::setup_matrices()
|
||||
{
|
||||
|
||||
::glMatrixMode(GL_PROJECTION);
|
||||
OpenGLMatrices.load_matrix(m_renderpass.camera.projection());
|
||||
|
||||
/*
|
||||
if( ( m_renderpass.draw_mode == rendermode::color )
|
||||
&& ( m_environmentcubetexturesupport ) ) {
|
||||
// special case, for colour render pass setup texture matrix for reflections cube map
|
||||
select_unit( m_helpertextureunit );
|
||||
::glMatrixMode( GL_TEXTURE );
|
||||
::glPushMatrix();
|
||||
::glMultMatrixf( glm::value_ptr( glm::inverse( glm::mat4{ glm::mat3{ m_renderpass.camera.modelview() } } ) ) );
|
||||
select_unit( m_diffusetextureunit );
|
||||
}
|
||||
*/
|
||||
|
||||
// trim modelview matrix just to rotation, since rendering is done in camera-centric world space
|
||||
::glMatrixMode(GL_MODELVIEW);
|
||||
OpenGLMatrices.load_matrix(glm::mat4(glm::mat3(m_renderpass.camera.modelview())));
|
||||
@@ -777,11 +825,16 @@ void opengl_renderer::setup_matrices()
|
||||
|
||||
void opengl_renderer::setup_drawing(bool const Alpha)
|
||||
{
|
||||
|
||||
if (true == Alpha)
|
||||
{
|
||||
::glEnable(GL_BLEND);
|
||||
else
|
||||
::glDisable(GL_BLEND);
|
||||
m_blendphase = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
::glDisable(GL_BLEND);
|
||||
m_blendphase = false;
|
||||
}
|
||||
|
||||
switch (m_renderpass.draw_mode)
|
||||
{
|
||||
@@ -832,6 +885,19 @@ void opengl_renderer::setup_shadow_map(opengl_texture *tex, renderpass_config co
|
||||
}
|
||||
}
|
||||
|
||||
void opengl_renderer::setup_env_map(gl::cubemap *tex)
|
||||
{
|
||||
if (tex)
|
||||
tex->bind(GL_TEXTURE0 + gl::MAX_TEXTURES + 1);
|
||||
else
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + gl::MAX_TEXTURES + 1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
m_textures.reset_unit_cache();
|
||||
}
|
||||
|
||||
void opengl_renderer::setup_environment_light(TEnvironmentType const Environment)
|
||||
{
|
||||
|
||||
@@ -895,20 +961,39 @@ bool opengl_renderer::Render(world_environment *Environment)
|
||||
gfx::opengl_vbogeometrybank::reset();
|
||||
|
||||
// celestial bodies
|
||||
float const duskfactor = 1.0f - clamp( std::abs( Environment->m_sun.getAngle() ), 0.0f, 12.0f ) / 12.0f;
|
||||
glm::vec3 suncolor = interpolate(
|
||||
glm::vec3( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ),
|
||||
glm::vec3( 235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f ),
|
||||
duskfactor );
|
||||
float const duskfactor = 1.0f - clamp(std::abs(Environment->m_sun.getAngle()), 0.0f, 12.0f) / 12.0f;
|
||||
glm::vec3 suncolor = interpolate(glm::vec3(255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f), glm::vec3(235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f), duskfactor);
|
||||
m_textures.reset_unit_cache();
|
||||
|
||||
// m7t: restore celestial bodies
|
||||
|
||||
// stars
|
||||
if (Environment->m_stars.m_stars != nullptr)
|
||||
{
|
||||
// setup
|
||||
::glPushMatrix();
|
||||
::glRotatef(Environment->m_stars.m_latitude, 1.f, 0.f, 0.f); // ustawienie osi OY na północ
|
||||
::glRotatef(-std::fmod((float)Global.fTimeAngleDeg, 360.f), 0.f, 1.f, 0.f); // obrót dobowy osi OX
|
||||
|
||||
// render
|
||||
GfxRenderer.Render(Environment->m_stars.m_stars, nullptr, 1.0);
|
||||
|
||||
// post-render cleanup
|
||||
::glPopMatrix();
|
||||
}
|
||||
|
||||
// clouds
|
||||
if (Environment->m_clouds.mdCloud)
|
||||
{
|
||||
// setup
|
||||
// m7t set cloud color
|
||||
glm::vec3 color = interpolate(Environment->m_skydome.GetAverageColor(), suncolor, duskfactor * 0.25f) * interpolate(1.f, 0.35f, Global.Overcast / 2.f) // overcast darkens the clouds
|
||||
* 2.5f;
|
||||
|
||||
// write cloud color into material
|
||||
TSubModel *mdl = Environment->m_clouds.mdCloud->Root;
|
||||
if (mdl->m_material != null_handle)
|
||||
m_materials.material(mdl->m_material).params[0] = glm::vec4(color, 1.0f);
|
||||
|
||||
// render
|
||||
Render(Environment->m_clouds.mdCloud, nullptr, 100.0);
|
||||
Render_Alpha(Environment->m_clouds.mdCloud, nullptr, 100.0);
|
||||
@@ -986,13 +1071,17 @@ std::shared_ptr<gl::program> opengl_renderer::Fetch_Shader(const std::string &na
|
||||
|
||||
void opengl_renderer::Bind_Material(material_handle const Material)
|
||||
{
|
||||
|
||||
if (Material != null_handle)
|
||||
{
|
||||
auto &material = m_materials.material(Material);
|
||||
for (size_t i = 0; i < gl::MAX_PARAMS; i++)
|
||||
model_ubs.param[i] = material.params[i];
|
||||
model_ubs.opacity = material.opacity;
|
||||
|
||||
if (m_blendphase)
|
||||
model_ubs.opacity = 0.0f;
|
||||
else
|
||||
model_ubs.opacity = 1.0f;
|
||||
|
||||
material.shader->bind();
|
||||
|
||||
size_t unit = 0;
|
||||
@@ -1028,14 +1117,12 @@ void opengl_renderer::Bind_Material_Shadow(material_handle const Material)
|
||||
|
||||
opengl_material const &opengl_renderer::Material(material_handle const Material) const
|
||||
{
|
||||
|
||||
return m_materials.material(Material);
|
||||
}
|
||||
|
||||
texture_handle opengl_renderer::Fetch_Texture(std::string const &Filename, bool const Loadnow)
|
||||
texture_handle opengl_renderer::Fetch_Texture(std::string const &Filename, bool const Loadnow, GLint format_hint)
|
||||
{
|
||||
|
||||
return m_textures.create(Filename, Loadnow);
|
||||
return m_textures.create(Filename, Loadnow, format_hint);
|
||||
}
|
||||
|
||||
void opengl_renderer::Bind_Texture(size_t Unit, texture_handle const Texture)
|
||||
@@ -1111,6 +1198,11 @@ void opengl_renderer::Render(scene::basic_region *Region)
|
||||
break;
|
||||
}
|
||||
case rendermode::reflections:
|
||||
{
|
||||
// for the time being reflections render only terrain geometry
|
||||
Render(std::begin(m_sectionqueue), std::end(m_sectionqueue));
|
||||
break;
|
||||
}
|
||||
case rendermode::pickcontrols:
|
||||
default:
|
||||
{
|
||||
@@ -1127,14 +1219,8 @@ void opengl_renderer::Render(section_sequence::iterator First, section_sequence:
|
||||
{
|
||||
case rendermode::color:
|
||||
case rendermode::reflections:
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
case rendermode::shadows:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case rendermode::pickscenery:
|
||||
{
|
||||
// non-interactive scenery elements get neutral colour
|
||||
@@ -1142,10 +1228,8 @@ void opengl_renderer::Render(section_sequence::iterator First, section_sequence:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (First != Last)
|
||||
{
|
||||
@@ -1393,10 +1477,9 @@ void opengl_renderer::Render(scene::shape_node const &Shape, bool const Ignorera
|
||||
switch (m_renderpass.draw_mode)
|
||||
{
|
||||
case rendermode::color:
|
||||
case rendermode::reflections:
|
||||
Bind_Material(data.material);
|
||||
break;
|
||||
case rendermode::reflections:
|
||||
break;
|
||||
case rendermode::shadows:
|
||||
Bind_Material_Shadow(data.material);
|
||||
break;
|
||||
@@ -1655,12 +1738,12 @@ bool opengl_renderer::Render_cab(TDynamicObject const *Dynamic, bool const Alpha
|
||||
break;
|
||||
}
|
||||
case rendermode::cabshadows:
|
||||
if( true == Alpha )
|
||||
if (true == Alpha)
|
||||
// translucent parts
|
||||
Render_Alpha( Dynamic->mdKabina, Dynamic->Material(), 0.0 );
|
||||
Render_Alpha(Dynamic->mdKabina, Dynamic->Material(), 0.0);
|
||||
else
|
||||
// opaque parts
|
||||
Render( Dynamic->mdKabina, Dynamic->Material(), 0.0 );
|
||||
Render(Dynamic->mdKabina, Dynamic->Material(), 0.0);
|
||||
break;
|
||||
case rendermode::pickcontrols:
|
||||
{
|
||||
@@ -1932,6 +2015,8 @@ void opengl_renderer::Render(TSubModel *Submodel)
|
||||
setup_shadow_color( m_shadowcolor );
|
||||
*/
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
::glPopMatrix();
|
||||
}
|
||||
}
|
||||
@@ -1954,14 +2039,14 @@ void opengl_renderer::Render(TSubModel *Submodel)
|
||||
{
|
||||
if (Global.fLuminance < Submodel->fLight)
|
||||
{
|
||||
|
||||
Bind_Material(null_handle);
|
||||
Bind_Material(Submodel->m_material);
|
||||
|
||||
// main draw call
|
||||
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
|
||||
model_ubo->update(model_ubs);
|
||||
glPointSize(2.0f * 2.0f);
|
||||
|
||||
// m_geometry.draw( Submodel->m_geometry, gfx::color_streams );
|
||||
m_geometry.draw(Submodel->m_geometry);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2434,9 +2519,7 @@ void opengl_renderer::Render_Alpha(scene::lines_node const &Lines)
|
||||
}
|
||||
// setup
|
||||
auto const distance{static_cast<float>(std::sqrt(distancesquared))};
|
||||
auto const linealpha = (data.line_width > 0.f ? glm::clamp(10.f * data.line_width /
|
||||
std::max(0.5f * data.area.radius + 1.f,
|
||||
distance - (0.5f * data.area.radius)), 0.0f, 1.0f) :
|
||||
auto const linealpha = (data.line_width > 0.f ? glm::clamp(10.f * data.line_width / std::max(0.5f * data.area.radius + 1.f, distance - (0.5f * data.area.radius)), 0.0f, 1.0f) :
|
||||
1.f); // negative width means the lines are always opague
|
||||
if (m_widelines_supported)
|
||||
glLineWidth(clamp(0.5f * linealpha + data.line_width * data.area.radius / 1000.f, 1.f, 8.f));
|
||||
@@ -2720,29 +2803,30 @@ void opengl_renderer::Render_Alpha(TSubModel *Submodel)
|
||||
// reduce the glare in bright daylight
|
||||
glarelevel = clamp(glarelevel - static_cast<float>(Global.fLuminance), 0.f, 1.f);
|
||||
|
||||
if( glarelevel > 0.0f ) {
|
||||
glDepthMask( GL_FALSE );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
||||
if (glarelevel > 0.0f)
|
||||
{
|
||||
glDepthMask(GL_FALSE);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
|
||||
::glPushMatrix();
|
||||
::glLoadIdentity(); // macierz jedynkowa
|
||||
::glTranslatef( lightcenter.x, lightcenter.y, lightcenter.z ); // początek układu zostaje bez zmian
|
||||
::glRotated( std::atan2( lightcenter.x, lightcenter.z ) * 180.0 / M_PI, 0.0, 1.0, 0.0 ); // jedynie obracamy w pionie o kąt
|
||||
::glPushMatrix();
|
||||
::glLoadIdentity(); // macierz jedynkowa
|
||||
::glTranslatef(lightcenter.x, lightcenter.y, lightcenter.z); // początek układu zostaje bez zmian
|
||||
::glRotated(std::atan2(lightcenter.x, lightcenter.z) * 180.0 / M_PI, 0.0, 1.0, 0.0); // jedynie obracamy w pionie o kąt
|
||||
|
||||
m_billboard_shader->bind();
|
||||
Bind_Texture( 0, m_glaretexture );
|
||||
Bind_Texture(0, m_glaretexture);
|
||||
m_textures.reset_unit_cache();
|
||||
model_ubs.param[0] = glm::vec4(glm::vec3(Submodel->f4Diffuse), glarelevel);
|
||||
|
||||
// main draw call
|
||||
// main draw call
|
||||
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
|
||||
model_ubo->update(model_ubs);
|
||||
m_geometry.draw( m_billboardgeometry );
|
||||
model_ubo->update(model_ubs);
|
||||
m_geometry.draw(m_billboardgeometry);
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
::glPopMatrix();
|
||||
::glPopMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2825,6 +2909,8 @@ TSubModel const *opengl_renderer::Update_Pick_Control()
|
||||
|
||||
scene::basic_node const *opengl_renderer::Update_Pick_Node()
|
||||
{
|
||||
//m7t: restore picking
|
||||
/*
|
||||
Render_pass(rendermode::pickscenery);
|
||||
|
||||
// determine point to examine
|
||||
@@ -2852,6 +2938,8 @@ scene::basic_node const *opengl_renderer::Update_Pick_Node()
|
||||
|
||||
m_picksceneryitem = node;
|
||||
return node;
|
||||
*/
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void opengl_renderer::Update(double const Deltatime)
|
||||
@@ -3040,7 +3128,7 @@ void opengl_renderer::Update_Lights(light_array &Lights)
|
||||
light_ubs.lights_count = light_i;
|
||||
|
||||
light_ubs.fog_color = Global.FogColor;
|
||||
if( Global.fFogEnd > 0 )
|
||||
if (Global.fFogEnd > 0)
|
||||
light_ubs.fog_density = 1.0f / Global.fFogEnd;
|
||||
else
|
||||
light_ubs.fog_density = 0.0f;
|
||||
|
||||
12
renderer.h
12
renderer.h
@@ -24,6 +24,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "gl/renderbuffer.h"
|
||||
#include "gl/postfx.h"
|
||||
#include "gl/shader.h"
|
||||
#include "gl/cubemap.h"
|
||||
|
||||
#define EU07_USE_PICKING_FRAMEBUFFER
|
||||
//#define EU07_USE_DEBUG_SHADOWMAP
|
||||
@@ -157,7 +158,7 @@ class opengl_renderer
|
||||
|
||||
opengl_material const &Material(material_handle const Material) const;
|
||||
// texture methods
|
||||
texture_handle Fetch_Texture(std::string const &Filename, bool const Loadnow = true);
|
||||
texture_handle Fetch_Texture(std::string const &Filename, bool const Loadnow = true, GLint format_hint = GL_SRGB_ALPHA);
|
||||
void Bind_Texture(size_t Unit, texture_handle const Texture);
|
||||
opengl_texture &Texture(texture_handle const Texture) const;
|
||||
// utility methods
|
||||
@@ -227,6 +228,7 @@ class opengl_renderer
|
||||
void setup_matrices();
|
||||
void setup_drawing(bool const Alpha = false);
|
||||
void setup_shadow_map(opengl_texture *tex, renderpass_config conf);
|
||||
void setup_env_map(gl::cubemap *tex);
|
||||
void setup_environment_light(TEnvironmentType const Environment = e_flat);
|
||||
// runs jobs needed to generate graphics for specified render pass
|
||||
void Render_pass(rendermode const Mode);
|
||||
@@ -371,8 +373,16 @@ class opengl_renderer
|
||||
std::unique_ptr<gl::framebuffer> m_cabshadows_fb;
|
||||
std::unique_ptr<opengl_texture> m_cabshadows_tex;
|
||||
|
||||
std::unique_ptr<gl::framebuffer> m_env_fb;
|
||||
std::unique_ptr<gl::renderbuffer> m_env_rb;
|
||||
std::unique_ptr<gl::cubemap> m_env_tex;
|
||||
|
||||
std::unique_ptr<gl::cubemap> m_empty_cubemap;
|
||||
|
||||
material_handle m_invalid_material;
|
||||
|
||||
bool m_blendphase; // m7t: todo: remove kludge!
|
||||
|
||||
bool m_widelines_supported;
|
||||
};
|
||||
|
||||
|
||||
@@ -340,7 +340,7 @@ shape_node::convert( TSubModel const *Submodel ) {
|
||||
m_data.lighting.diffuse = Submodel->f4Diffuse;
|
||||
m_data.lighting.specular = Submodel->f4Specular;
|
||||
m_data.material = Submodel->m_material;
|
||||
m_data.translucent = ( true == GfxRenderer.Material( m_data.material ).opacity < 1.0f );
|
||||
m_data.translucent = ( GfxRenderer.Material( m_data.material ).opacity == 0.0f );
|
||||
// NOTE: we set unlimited view range typical for terrain, because we don't expect to convert any other 3d models
|
||||
m_data.rangesquared_max = std::numeric_limits<double>::max();
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
in vec2 f_coord;
|
||||
|
||||
#texture (tex1, 0, sRGB_A)
|
||||
uniform sampler2D tex1;
|
||||
|
||||
void main()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
in vec3 f_normal;
|
||||
in vec2 f_coord;
|
||||
|
||||
#texture (tex1, 0, sRGB_A)
|
||||
uniform sampler2D tex1;
|
||||
|
||||
#include <common>
|
||||
|
||||
@@ -7,8 +7,11 @@ in vec4 f_light_pos;
|
||||
|
||||
#include <common>
|
||||
|
||||
#texture (tex1, 0, sRGB_A)
|
||||
uniform sampler2D tex1;
|
||||
|
||||
uniform sampler2DShadow shadowmap;
|
||||
uniform samplerCube envmap;
|
||||
|
||||
float calc_shadow()
|
||||
{
|
||||
@@ -89,8 +92,16 @@ void main()
|
||||
{
|
||||
vec4 tex_color = texture(tex1, f_coord);
|
||||
|
||||
if (opacity == 0.0f && tex_color.a < 0.9f)
|
||||
discard;
|
||||
if (opacity == 0.0f)
|
||||
{
|
||||
//blending
|
||||
}
|
||||
else
|
||||
{
|
||||
//test
|
||||
if (tex_color.a < 0.5f)
|
||||
discard;
|
||||
}
|
||||
|
||||
float shadow = calc_shadow();
|
||||
vec3 result = ambient * 0.3 + vec3(1.0) * emission;
|
||||
|
||||
123
shaders/mat_mir.frag
Normal file
123
shaders/mat_mir.frag
Normal file
@@ -0,0 +1,123 @@
|
||||
#version 330
|
||||
|
||||
in vec3 f_normal;
|
||||
in vec2 f_coord;
|
||||
in vec3 f_pos;
|
||||
in vec4 f_light_pos;
|
||||
|
||||
#include <common>
|
||||
|
||||
#texture (tex1, 0, sRGB_A)
|
||||
uniform sampler2D tex1;
|
||||
|
||||
uniform sampler2DShadow shadowmap;
|
||||
uniform samplerCube envmap;
|
||||
|
||||
float calc_shadow()
|
||||
{
|
||||
vec3 coords = f_light_pos.xyz / f_light_pos.w;
|
||||
|
||||
// do something better
|
||||
float bias = 0.0001f;
|
||||
|
||||
//sampler PCF
|
||||
//float shadow = texture(shadowmap, vec3(coords.xy, coords.z - bias));
|
||||
|
||||
//sampler PCF + PCF
|
||||
float shadow = 0.0;
|
||||
vec2 texel = 1.0 / textureSize(shadowmap, 0);
|
||||
for (float y = -1.5; y <= 1.5; y += 1.0)
|
||||
for (float x = -1.5; x <= 1.5; x += 1.0)
|
||||
shadow += texture(shadowmap, coords.xyz + vec3(vec2(x, y) * texel, -bias));
|
||||
shadow /= 16.0;
|
||||
|
||||
if (coords.z > 1.0f)
|
||||
shadow = 1.0f;
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
vec3 apply_fog(vec3 color)
|
||||
{
|
||||
float sun_amount = 0.0;
|
||||
if (lights_count >= 1U && lights[0].type == LIGHT_DIR)
|
||||
sun_amount = max(dot(normalize(f_pos), normalize(-lights[0].dir)), 0.0);
|
||||
vec3 fog_color_v = mix(fog_color, lights[0].color, pow(sun_amount, 30.0));
|
||||
float fog_amount_v = 1.0 - min(1.0, exp(-length(f_pos) * fog_density));
|
||||
return mix(color, fog_color_v, fog_amount_v);
|
||||
}
|
||||
|
||||
float calc_light(vec3 light_dir)
|
||||
{
|
||||
vec3 normal = normalize(f_normal);
|
||||
vec3 view_dir = normalize(vec3(0.0f, 0.0f, 0.0f) - f_pos);
|
||||
vec3 halfway_dir = normalize(light_dir + view_dir);
|
||||
|
||||
float diffuse_v = max(dot(normal, light_dir), 0.0);
|
||||
float specular_v = pow(max(dot(normal, halfway_dir), 0.0), 15.0);
|
||||
|
||||
return specular_v + diffuse_v;
|
||||
}
|
||||
|
||||
float calc_point_light(light_s light)
|
||||
{
|
||||
vec3 light_dir = normalize(light.pos - f_pos);
|
||||
float val = calc_light(light_dir);
|
||||
|
||||
float distance = length(light.pos - f_pos);
|
||||
float atten = 1.0f / (1.0f + light.linear * distance + light.quadratic * (distance * distance));
|
||||
|
||||
return val * atten;
|
||||
}
|
||||
|
||||
float calc_spot_light(light_s light)
|
||||
{
|
||||
vec3 light_dir = normalize(light.pos - f_pos);
|
||||
|
||||
float theta = dot(light_dir, normalize(-light.dir));
|
||||
float epsilon = light.in_cutoff - light.out_cutoff;
|
||||
float intensity = clamp((theta - light.out_cutoff) / epsilon, 0.0, 1.0);
|
||||
|
||||
float point = calc_point_light(light);
|
||||
return point * intensity;
|
||||
}
|
||||
|
||||
float calc_dir_light(light_s light)
|
||||
{
|
||||
vec3 light_dir = normalize(-light.dir);
|
||||
return calc_light(light_dir);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(tex1, f_coord);
|
||||
|
||||
if (opacity == 0.0f && tex_color.a < 0.9f)
|
||||
discard;
|
||||
|
||||
float shadow = calc_shadow();
|
||||
vec3 result = ambient * 0.3 + vec3(1.0) * emission;
|
||||
for (uint i = 0U; i < lights_count; i++)
|
||||
{
|
||||
light_s light = lights[i];
|
||||
float part = 0.0;
|
||||
|
||||
if (light.type == LIGHT_SPOT)
|
||||
part = calc_spot_light(light);
|
||||
else if (light.type == LIGHT_POINT)
|
||||
part = calc_point_light(light);
|
||||
else if (light.type == LIGHT_DIR)
|
||||
part = calc_dir_light(light);
|
||||
|
||||
if (i == 0U)
|
||||
part *= shadow;
|
||||
result += light.color * part;
|
||||
}
|
||||
|
||||
vec3 R = reflect(f_pos, normalize(f_normal));
|
||||
vec3 r = texture(envmap, R).rgb;
|
||||
r *= vec3(1.0, 0.84, 0.2);
|
||||
|
||||
vec3 c = apply_fog(result * tex_color.xyz);
|
||||
gl_FragColor = vec4(c * 0.05 + r * 0.95, tex_color.w);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ in vec3 f_normal;
|
||||
in vec2 f_coord;
|
||||
in vec3 f_pos;
|
||||
|
||||
#texture (tex1, 0, sRGB_A)
|
||||
uniform sampler2D tex1;
|
||||
|
||||
#include <common>
|
||||
@@ -11,5 +12,5 @@ uniform sampler2D tex1;
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(tex1, f_coord);
|
||||
gl_FragColor = vec4(tex_color.xyz * ambient, tex_color.a);
|
||||
gl_FragColor = tex_color * param[0];
|
||||
}
|
||||
|
||||
@@ -6,7 +6,10 @@ in vec3 f_pos;
|
||||
in mat3 f_tbn;
|
||||
in vec4 f_tangent;
|
||||
|
||||
#texture (tex1, 0, sRGB_A)
|
||||
uniform sampler2D tex1;
|
||||
|
||||
#texture (tex2, 1, RGB)
|
||||
uniform sampler2D tex2;
|
||||
|
||||
#include <common>
|
||||
|
||||
17
shaders/mat_stars.frag
Normal file
17
shaders/mat_stars.frag
Normal file
@@ -0,0 +1,17 @@
|
||||
#version 330
|
||||
|
||||
#include <common>
|
||||
|
||||
in vec3 f_normal;
|
||||
|
||||
void main()
|
||||
{
|
||||
float x = (gl_PointCoord.x - 0.5f) * 2.0f;
|
||||
float y = (gl_PointCoord.y - 0.5f) * 2.0f;
|
||||
float dist2 = abs(x * x + y * y);
|
||||
if (dist2 > 0.5f * 0.5f)
|
||||
discard;
|
||||
|
||||
// color data is shared with normals, ugh
|
||||
gl_FragColor = vec4(f_normal, 1.0f);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ out vec4 FragColor;
|
||||
|
||||
in vec2 f_coords;
|
||||
|
||||
#texture (tex1, 0, RGB)
|
||||
uniform sampler2D tex1;
|
||||
|
||||
vec3 reinhard(vec3 x)
|
||||
|
||||
Reference in New Issue
Block a user