16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-19 23:49:18 +02:00
This commit is contained in:
milek7
2018-07-15 23:46:53 +02:00
parent 794093dad4
commit 4c855d5980
26 changed files with 690 additions and 183 deletions

View File

@@ -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;
}

View File

@@ -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"

View File

@@ -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;
}

View File

@@ -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
}

View File

@@ -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 );

View File

@@ -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 );

View File

@@ -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
View 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
View 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();
};
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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();
};

View File

@@ -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();

View File

@@ -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;
};
//---------------------------------------------------------------------------

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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();

View File

@@ -2,6 +2,7 @@
in vec2 f_coord;
#texture (tex1, 0, sRGB_A)
uniform sampler2D tex1;
void main()

View File

@@ -3,6 +3,7 @@
in vec3 f_normal;
in vec2 f_coord;
#texture (tex1, 0, sRGB_A)
uniform sampler2D tex1;
#include <common>

View File

@@ -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
View 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);
}

View File

@@ -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];
}

View File

@@ -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
View 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);
}

View File

@@ -3,6 +3,7 @@ out vec4 FragColor;
in vec2 f_coords;
#texture (tex1, 0, RGB)
uniform sampler2D tex1;
vec3 reinhard(vec3 x)