misc...
	* disabled depth write for qer_trans surfs and highlight (=any amount of layers is visible)
	* 20x faster light radii rendering
	* light radii are coloured and additive
	* anisotropic textures filtering option (def = yes)
This commit is contained in:
Garux 2017-08-02 09:33:51 +03:00
parent bc5dcc1699
commit 1df30a3b8c
6 changed files with 229 additions and 42 deletions

View File

@ -61,8 +61,8 @@ enum ESort
eSortMultiLast = 1023, eSortMultiLast = 1023,
eSortOverbrighten = 1024, eSortOverbrighten = 1024,
eSortFullbright = 1025, eSortFullbright = 1025,
eSortHighlight = 1026, eSortTranslucent = 1026,
eSortTranslucent = 1027, eSortHighlight = 1027,
eSortOverlayFirst = 1028, eSortOverlayFirst = 1028,
eSortOverlayLast = 2047, eSortOverlayLast = 2047,
eSortControlFirst = 2048, eSortControlFirst = 2048,

View File

@ -159,6 +159,10 @@ inline EntityClassAttributePair& EntityClass_insertAttribute( EntityClass& entit
} }
inline void buffer_write_colour_add( char buffer[128], const Colour3& colour ){
sprintf( buffer, "{%g %g %g}", colour[0], colour[1], colour[2] );
}
inline void buffer_write_colour_fill( char buffer[128], const Colour3& colour ){ inline void buffer_write_colour_fill( char buffer[128], const Colour3& colour ){
sprintf( buffer, "(%g %g %g)", colour[0], colour[1], colour[2] ); sprintf( buffer, "(%g %g %g)", colour[0], colour[1], colour[2] );
} }
@ -171,6 +175,18 @@ inline void buffer_write_colour_blend( char buffer[128], const Colour3& colour )
sprintf( buffer, "[%g %g %g]", colour[0], colour[1], colour[2] ); sprintf( buffer, "[%g %g %g]", colour[0], colour[1], colour[2] );
} }
inline Shader* colour_capture_state_add( const Colour3& colour ){
char buffer[128];
buffer_write_colour_add( buffer, colour );
return GlobalShaderCache().capture( buffer );
}
inline void colour_release_state_add( const Colour3& colour ){
char buffer[128];
buffer_write_colour_add( buffer, colour );
GlobalShaderCache().release( buffer );
}
inline Shader* colour_capture_state_fill( const Colour3& colour ){ inline Shader* colour_capture_state_fill( const Colour3& colour ){
char buffer[128]; char buffer[128];
buffer_write_colour_fill( buffer, colour ); buffer_write_colour_fill( buffer, colour );

View File

@ -49,12 +49,15 @@ class Colour
{ {
Callback m_colourChanged; Callback m_colourChanged;
Shader* m_state; Shader* m_state;
Shader* m_state_additive;
void capture_state(){ void capture_state(){
m_state = colour_capture_state_fill( m_colour ); m_state = colour_capture_state_fill( m_colour );
m_state_additive = colour_capture_state_add( m_colour );
} }
void release_state(){ void release_state(){
colour_release_state_fill( m_colour ); colour_release_state_fill( m_colour );
colour_release_state_add( m_colour );
} }
public: public:
@ -86,6 +89,9 @@ void write( Entity* entity ) const {
Shader* state() const { Shader* state() const {
return m_state; return m_state;
} }
Shader* state_additive() const {
return m_state_additive;
}
}; };
#endif #endif

View File

@ -66,7 +66,61 @@
#include "entity.h" #include "entity.h"
extern bool g_newLightDraw; extern bool g_newLightDraw;
#define SPHERE_FILL_SIDES 16
#define SPHERE_FILL_POINTS SPHERE_FILL_SIDES * (SPHERE_FILL_SIDES - 1) * 6 + SPHERE_FILL_SIDES * 3
#define SPHERE_WIRE_SIDES 24
#define SPHERE_WIRE_POINTS SPHERE_WIRE_SIDES * 3
void sphere_construct_fill( Vector3 (&radiiPoints)[SPHERE_FILL_POINTS] ){
const double dt = c_2pi / static_cast<double>( SPHERE_FILL_SIDES );
const double dp = c_pi / static_cast<double>( SPHERE_FILL_SIDES );
int k = 0;
for ( int i = 0; i <= SPHERE_FILL_SIDES - 1; ++i )
{
for ( int j = 0; j <= SPHERE_FILL_SIDES - 2; ++j )
{
const double t = i * dt;
const double p = ( j * dp ) - ( c_pi / 2.0 );
radiiPoints[k++] = vector3_for_spherical( t, p );
radiiPoints[k++] = vector3_for_spherical( t, p + dp );
radiiPoints[k++] = vector3_for_spherical( t + dt, p + dp );
radiiPoints[k++] = vector3_for_spherical( t, p );
radiiPoints[k++] = vector3_for_spherical( t + dt, p + dp );
radiiPoints[k++] = vector3_for_spherical( t + dt, p );
}
}
{
const double p = ( SPHERE_FILL_SIDES - 1 ) * dp - ( c_pi / 2.0 );
for ( int i = 0; i <= SPHERE_FILL_SIDES - 1; ++i )
{
const double t = i * dt;
radiiPoints[k++] = vector3_for_spherical( t, p );
radiiPoints[k++] = vector3_for_spherical( t + dt, p + dp );
radiiPoints[k++] = vector3_for_spherical( t + dt, p );
}
}
}
void sphere_draw_fill_( const Vector3& origin, float radius, const Vector3 (&radiiPoints)[SPHERE_FILL_POINTS] ){
if ( radius <= 0 ) {
return;
}
glBegin( GL_TRIANGLES );
for ( int i = 0; i < SPHERE_FILL_POINTS; ++i )
{
glVertex3fv( vector3_to_array( vector3_added( origin, vector3_scaled( radiiPoints[i], radius ) ) ) );
}
glEnd();
}
#if 0
void sphere_draw_fill( const Vector3& origin, float radius, int sides ){ void sphere_draw_fill( const Vector3& origin, float radius, int sides ){
if ( radius <= 0 ) { if ( radius <= 0 ) {
return; return;
@ -195,6 +249,67 @@ void sphere_draw_wire( const Vector3& origin, float radius, int sides ){
glEnd(); glEnd();
} }
} }
#endif // 0
void sphere_construct_wire( Vector3 (&radiiPoints)[SPHERE_WIRE_POINTS] ){
int k = 0;
for ( int i = 0; i < SPHERE_WIRE_SIDES; i++ )
{
double ds = sin( ( i * 2 * c_pi ) / SPHERE_WIRE_SIDES );
double dc = cos( ( i * 2 * c_pi ) / SPHERE_WIRE_SIDES );
radiiPoints[k++] =
Vector3(
static_cast<float>( dc ),
static_cast<float>( ds ),
0.f
);
}
for ( int i = 0; i < SPHERE_WIRE_SIDES; i++ )
{
double ds = sin( ( i * 2 * c_pi ) / SPHERE_WIRE_SIDES );
double dc = cos( ( i * 2 * c_pi ) / SPHERE_WIRE_SIDES );
radiiPoints[k++] =
Vector3(
static_cast<float>( dc ),
0.f,
static_cast<float>( ds )
);
}
for ( int i = 0; i < SPHERE_WIRE_SIDES; i++ )
{
double ds = sin( ( i * 2 * c_pi ) / SPHERE_WIRE_SIDES );
double dc = cos( ( i * 2 * c_pi ) / SPHERE_WIRE_SIDES );
radiiPoints[k++] =
Vector3(
0.f,
static_cast<float>( dc ),
static_cast<float>( ds )
);
}
}
void sphere_draw_wire_( const Vector3& origin, float radius, const Vector3 (&radiiPoints)[SPHERE_WIRE_POINTS] ){
int k = 0;
for( int j = 0; j < 3; j++ )
{
glBegin( GL_LINE_LOOP );
for ( int i = 0; i < SPHERE_WIRE_SIDES; i++ )
{
glVertex3fv( vector3_to_array( vector3_added( origin, vector3_scaled( radiiPoints[k++], radius ) ) ) );
}
glEnd();
}
}
void light_draw_box_lines( const Vector3& origin, const Vector3 points[8] ){ void light_draw_box_lines( const Vector3& origin, const Vector3 points[8] ){
//draw lines from the center of the bbox to the corners //draw lines from the center of the bbox to the corners
@ -226,7 +341,7 @@ void light_draw_box_lines( const Vector3& origin, const Vector3 points[8] ){
glEnd(); glEnd();
} }
#if 0
void light_draw_radius_wire( const Vector3& origin, const float envelope[3] ){ void light_draw_radius_wire( const Vector3& origin, const float envelope[3] ){
if ( envelope[0] > 0 ) { if ( envelope[0] > 0 ) {
sphere_draw_wire( origin, envelope[0], 24 ); sphere_draw_wire( origin, envelope[0], 24 );
@ -238,7 +353,19 @@ void light_draw_radius_wire( const Vector3& origin, const float envelope[3] ){
sphere_draw_wire( origin, envelope[2], 24 ); sphere_draw_wire( origin, envelope[2], 24 );
} }
} }
#endif // 0
void light_draw_radius_wire_( const Vector3& origin, const float envelope[3], const Vector3 (&radiiPoints)[SPHERE_WIRE_POINTS] ){
if ( envelope[0] > 0 ) {
sphere_draw_wire_( origin, envelope[0], radiiPoints );
}
if ( envelope[1] > 0 ) {
sphere_draw_wire_( origin, envelope[1], radiiPoints );
}
if ( envelope[2] > 0 ) {
sphere_draw_wire_( origin, envelope[2], radiiPoints );
}
}
#if 0
void light_draw_radius_fill( const Vector3& origin, const float envelope[3] ){ void light_draw_radius_fill( const Vector3& origin, const float envelope[3] ){
if ( envelope[0] > 0 ) { if ( envelope[0] > 0 ) {
sphere_draw_fill( origin, envelope[0], 16 ); sphere_draw_fill( origin, envelope[0], 16 );
@ -250,6 +377,18 @@ void light_draw_radius_fill( const Vector3& origin, const float envelope[3] ){
sphere_draw_fill( origin, envelope[2], 16 ); sphere_draw_fill( origin, envelope[2], 16 );
} }
} }
#endif // 0
void light_draw_radius_fill_( const Vector3& origin, const float envelope[3], const Vector3 (&radiiPoints)[SPHERE_FILL_POINTS] ){
if ( envelope[0] > 0 ) {
sphere_draw_fill_( origin, envelope[0], radiiPoints );
}
if ( envelope[1] > 0 ) {
sphere_draw_fill_( origin, envelope[1], radiiPoints );
}
if ( envelope[2] > 0 ) {
sphere_draw_fill_( origin, envelope[2], radiiPoints );
}
}
void light_vertices( const AABB& aabb_light, Vector3 points[6] ){ void light_vertices( const AABB& aabb_light, Vector3 points[6] ){
Vector3 max( vector3_added( aabb_light.origin, aabb_light.extents ) ); Vector3 max( vector3_added( aabb_light.origin, aabb_light.extents ) );
@ -564,33 +703,41 @@ class RenderLightRadiiWire : public OpenGLRenderable
LightRadii& m_radii; LightRadii& m_radii;
const Vector3& m_origin; const Vector3& m_origin;
public: public:
static Vector3 m_radiiPoints[SPHERE_WIRE_POINTS];
RenderLightRadiiWire( LightRadii& radii, const Vector3& origin ) : m_radii( radii ), m_origin( origin ){ RenderLightRadiiWire( LightRadii& radii, const Vector3& origin ) : m_radii( radii ), m_origin( origin ){
} }
void render( RenderStateFlags state ) const { void render( RenderStateFlags state ) const {
light_draw_radius_wire( m_origin, m_radii.m_radii ); //light_draw_radius_wire( m_origin, m_radii.m_radii );
light_draw_radius_wire_( m_origin, m_radii.m_radii, m_radiiPoints );
} }
}; };
Vector3 RenderLightRadiiWire::m_radiiPoints[SPHERE_WIRE_POINTS] = {g_vector3_identity};
class RenderLightRadiiFill : public OpenGLRenderable class RenderLightRadiiFill : public OpenGLRenderable
{ {
LightRadii& m_radii; LightRadii& m_radii;
const Vector3& m_origin; const Vector3& m_origin;
public: public:
static Shader* m_state; //static Shader* m_state;
static Vector3 m_radiiPoints[SPHERE_FILL_POINTS];
RenderLightRadiiFill( LightRadii& radii, const Vector3& origin ) : m_radii( radii ), m_origin( origin ){ RenderLightRadiiFill( LightRadii& radii, const Vector3& origin ) : m_radii( radii ), m_origin( origin ){
} }
void render( RenderStateFlags state ) const { void render( RenderStateFlags state ) const {
light_draw_radius_fill( m_origin, m_radii.m_radii ); //light_draw_radius_fill( m_origin, m_radii.m_radii );
light_draw_radius_fill_( m_origin, m_radii.m_radii, m_radiiPoints );
} }
}; };
//Shader* RenderLightRadiiFill::m_state = 0;
Vector3 RenderLightRadiiFill::m_radiiPoints[SPHERE_FILL_POINTS] = {g_vector3_identity};
class RenderLightRadiiBox : public OpenGLRenderable class RenderLightRadiiBox : public OpenGLRenderable
{ {
const Vector3& m_origin; const Vector3& m_origin;
public: public:
mutable Vector3 m_points[8]; mutable Vector3 m_points[8];
static Shader* m_state; //static Shader* m_state;
RenderLightRadiiBox( const Vector3& origin ) : m_origin( origin ){ RenderLightRadiiBox( const Vector3& origin ) : m_origin( origin ){
} }
@ -610,8 +757,6 @@ void render( RenderStateFlags state ) const {
} }
}; };
Shader* RenderLightRadiiFill::m_state = 0;
class RenderLightCenter : public OpenGLRenderable class RenderLightCenter : public OpenGLRenderable
{ {
const Vector3& m_center; const Vector3& m_center;
@ -1104,18 +1249,20 @@ const AABB& localAABB() const {
mutable Matrix4 m_projectionOrientation; mutable Matrix4 m_projectionOrientation;
void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const { void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld, bool selected ) const {
renderer.SetState( m_entity.getEntityClass().m_state_wire, Renderer::eWireframeOnly ); renderer.SetState( m_colour.state(), Renderer::eWireframeOnly );
renderer.SetState( m_colour.state(), Renderer::eFullMaterials ); renderer.SetState( m_colour.state(), Renderer::eFullMaterials );
renderer.addRenderable( *this, localToWorld ); renderer.addRenderable( *this, localToWorld );
if ( selected && g_lightRadii && string_empty( m_entity.getKeyValue( "target" ) ) ) { if ( selected && g_lightRadii && string_empty( m_entity.getKeyValue( "target" ) ) ) {
if ( renderer.getStyle() == Renderer::eFullMaterials ) { if ( renderer.getStyle() == Renderer::eFullMaterials ) {
renderer.SetState( RenderLightRadiiFill::m_state, Renderer::eFullMaterials ); renderer.SetState( m_colour.state_add(), Renderer::eFullMaterials );
renderer.Highlight( Renderer::ePrimitive, false ); renderer.Highlight( Renderer::ePrimitive, false );
renderer.Highlight( Renderer::eFace, false );
renderer.addRenderable( m_radii_fill, localToWorld ); renderer.addRenderable( m_radii_fill, localToWorld );
} }
else else
{ {
renderer.Highlight( Renderer::ePrimitive, false );
renderer.addRenderable( m_radii_wire, localToWorld ); renderer.addRenderable( m_radii_wire, localToWorld );
} }
} }
@ -1709,11 +1856,13 @@ void Light_Construct( LightType lightType ){
LightShader::m_defaultShader = "lights/defaultProjectedLight"; LightShader::m_defaultShader = "lights/defaultProjectedLight";
#endif #endif
} }
RenderLightRadiiFill::m_state = GlobalShaderCache().capture( "$Q3MAP2_LIGHT_SPHERE" ); //RenderLightRadiiFill::m_state = GlobalShaderCache().capture( "$Q3MAP2_LIGHT_SPHERE" );
RenderLightCenter::m_state = GlobalShaderCache().capture( "$BIGPOINT" ); RenderLightCenter::m_state = GlobalShaderCache().capture( "$BIGPOINT" );
sphere_construct_fill( RenderLightRadiiFill::m_radiiPoints );
sphere_construct_wire( RenderLightRadiiWire::m_radiiPoints );
} }
void Light_Destroy(){ void Light_Destroy(){
GlobalShaderCache().release( "$Q3MAP2_LIGHT_SPHERE" ); //GlobalShaderCache().release( "$Q3MAP2_LIGHT_SPHERE" );
GlobalShaderCache().release( "$BIGPOINT" ); GlobalShaderCache().release( "$BIGPOINT" );
} }

View File

@ -1192,6 +1192,7 @@ Shader* capture( const char* name ){
|| *name == '[' || *name == '['
|| *name == '<' || *name == '<'
|| *name == '(' || *name == '('
|| *name == '{'
|| strchr( name, '\\' ) == 0, "shader name contains invalid characters: \"" << name << "\"" ); || strchr( name, '\\' ) == 0, "shader name contains invalid characters: \"" << name << "\"" );
#if DEBUG_SHADERS #if DEBUG_SHADERS
globalOutputStream() << "shaders capture: " << makeQuoted( name ) << '\n'; globalOutputStream() << "shaders capture: " << makeQuoted( name ) << '\n';
@ -2080,21 +2081,30 @@ void OpenGLShader::construct( const char* name ){
OpenGLState& state = appendDefaultPass(); OpenGLState& state = appendDefaultPass();
switch ( name[0] ) switch ( name[0] )
{ {
case '(': case '{': //add
sscanf( name, "{%g %g %g}", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] );
state.m_colour[3] = 1.0f;
state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL | RENDER_COLOURWRITE /*| RENDER_DEPTHWRITE*/ | RENDER_LIGHTING;
state.m_blend_src = GL_ONE;
state.m_blend_dst = GL_ONE;
state.m_sort = OpenGLState::eSortTranslucent;
break;
case '(': //fill
sscanf( name, "(%g %g %g)", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] ); sscanf( name, "(%g %g %g)", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] );
state.m_colour[3] = 1.0f; state.m_colour[3] = 1.0f;
state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
state.m_sort = OpenGLState::eSortFullbright; state.m_sort = OpenGLState::eSortFullbright;
break; break;
case '[': case '[': //blend
sscanf( name, "[%g %g %g]", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] ); sscanf( name, "[%g %g %g]", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] );
state.m_colour[3] = 0.5f; state.m_colour[3] = 0.5f;
state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND; state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND;
state.m_sort = OpenGLState::eSortTranslucent; state.m_sort = OpenGLState::eSortTranslucent;
break; break;
case '<': case '<': //wire
sscanf( name, "<%g %g %g>", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] ); sscanf( name, "<%g %g %g>", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] );
state.m_colour[3] = 1; state.m_colour[3] = 1;
state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
@ -2156,7 +2166,7 @@ void OpenGLShader::construct( const char* name ){
state.m_colour[1] = g_camwindow_globals.color_selbrushes3d[1]; state.m_colour[1] = g_camwindow_globals.color_selbrushes3d[1];
state.m_colour[2] = g_camwindow_globals.color_selbrushes3d[2]; state.m_colour[2] = g_camwindow_globals.color_selbrushes3d[2];
state.m_colour[3] = 0.3f; state.m_colour[3] = 0.3f;
state.m_state = RENDER_FILL | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; state.m_state = RENDER_FILL | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_BLEND | RENDER_COLOURWRITE/* | RENDER_DEPTHWRITE*/;
state.m_sort = OpenGLState::eSortHighlight; state.m_sort = OpenGLState::eSortHighlight;
state.m_depthfunc = GL_LEQUAL; state.m_depthfunc = GL_LEQUAL;
} }
@ -2203,6 +2213,7 @@ void OpenGLShader::construct( const char* name ){
state.m_sort = OpenGLState::eSortFullbright; state.m_sort = OpenGLState::eSortFullbright;
state.m_linewidth = 4; state.m_linewidth = 4;
} }
#if 0
else if ( string_equal( name + 1, "LIGHT_SPHERE" ) ) { else if ( string_equal( name + 1, "LIGHT_SPHERE" ) ) {
state.m_colour[0] = .15f * .95f; state.m_colour[0] = .15f * .95f;
state.m_colour[1] = .15f * .95f; state.m_colour[1] = .15f * .95f;
@ -2223,6 +2234,7 @@ void OpenGLShader::construct( const char* name ){
state.m_blend_dst = GL_ONE; state.m_blend_dst = GL_ONE;
state.m_sort = OpenGLState::eSortTranslucent; state.m_sort = OpenGLState::eSortTranslucent;
} }
#endif // 0
else if ( string_equal( name + 1, "WIRE_OVERLAY" ) ) { else if ( string_equal( name + 1, "WIRE_OVERLAY" ) ) {
#if 0 #if 0
state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
@ -2365,9 +2377,9 @@ void OpenGLShader::construct( const char* name ){
state.m_blend_src = convertBlendFactor( blendFunc.m_src ); state.m_blend_src = convertBlendFactor( blendFunc.m_src );
state.m_blend_dst = convertBlendFactor( blendFunc.m_dst ); state.m_blend_dst = convertBlendFactor( blendFunc.m_dst );
state.m_depthfunc = GL_LEQUAL; state.m_depthfunc = GL_LEQUAL;
if ( state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA ) { // if ( state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA ) {
state.m_state |= RENDER_DEPTHWRITE; // state.m_state |= RENDER_DEPTHWRITE;
} // }
} }
else else
{ {

View File

@ -49,7 +49,6 @@ enum ETexturesMode
eTextures_LINEAR = 3, eTextures_LINEAR = 3,
eTextures_LINEAR_MIPMAP_NEAREST = 4, eTextures_LINEAR_MIPMAP_NEAREST = 4,
eTextures_LINEAR_MIPMAP_LINEAR = 5, eTextures_LINEAR_MIPMAP_LINEAR = 5,
eTextures_MAX_ANISOTROPY = 6,
}; };
enum TextureCompressionFormat enum TextureCompressionFormat
@ -89,15 +88,6 @@ struct texture_globals_t
texture_globals_t g_texture_globals( GL_RGBA ); texture_globals_t g_texture_globals( GL_RGBA );
void SetTexParameters( ETexturesMode mode ){ void SetTexParameters( ETexturesMode mode ){
float maxAniso = QGL_maxTextureAnisotropy();
if ( maxAniso > 1 ) {
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f );
}
else
if ( mode == eTextures_MAX_ANISOTROPY ) {
mode = eTextures_LINEAR_MIPMAP_LINEAR;
}
switch ( mode ) switch ( mode )
{ {
case eTextures_NEAREST: case eTextures_NEAREST:
@ -124,15 +114,20 @@ void SetTexParameters( ETexturesMode mode ){
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
break; break;
case eTextures_MAX_ANISOTROPY:
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso );
break;
default: default:
globalOutputStream() << "invalid texture mode\n"; globalOutputStream() << "invalid texture mode\n";
} }
} }
void SetTexAnisotropy( bool anisotropy ){
float maxAniso = QGL_maxTextureAnisotropy();
if ( maxAniso > 1 ) {
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy ? maxAniso : 1.f );
}
}
ETexturesMode g_texture_mode = eTextures_LINEAR_MIPMAP_LINEAR; ETexturesMode g_texture_mode = eTextures_LINEAR_MIPMAP_LINEAR;
bool g_TextureAnisotropy = true;
@ -206,6 +201,7 @@ void LoadTextureRGBA( qtexture_t* q, unsigned char* pPixels, int nWidth, int nHe
glBindTexture( GL_TEXTURE_2D, q->texture_number ); glBindTexture( GL_TEXTURE_2D, q->texture_number );
SetTexParameters( g_texture_mode ); SetTexParameters( g_texture_mode );
SetTexAnisotropy( g_TextureAnisotropy );
int gl_width = 1; int gl_width = 1;
while ( gl_width < nWidth ) while ( gl_width < nWidth )
@ -557,11 +553,13 @@ void Textures_setModeChangedNotify( const Callback& notify ){
void Textures_ModeChanged(){ void Textures_ModeChanged(){
if ( g_texturesmap->realised() ) { if ( g_texturesmap->realised() ) {
SetTexParameters( g_texture_mode ); SetTexParameters( g_texture_mode );
SetTexAnisotropy( g_TextureAnisotropy );
for ( TexturesMap::iterator i = g_texturesmap->begin(); i != g_texturesmap->end(); ++i ) for ( TexturesMap::iterator i = g_texturesmap->begin(); i != g_texturesmap->end(); ++i )
{ {
glBindTexture( GL_TEXTURE_2D, ( *i ).value->texture_number ); glBindTexture( GL_TEXTURE_2D, ( *i ).value->texture_number );
SetTexParameters( g_texture_mode ); SetTexParameters( g_texture_mode );
SetTexAnisotropy( g_TextureAnisotropy );
} }
glBindTexture( GL_TEXTURE_2D, 0 ); glBindTexture( GL_TEXTURE_2D, 0 );
@ -577,6 +575,14 @@ void Textures_SetMode( ETexturesMode mode ){
} }
} }
void Textures_SetAnisotropy( bool anisotropy ){
if ( g_TextureAnisotropy != anisotropy ) {
g_TextureAnisotropy = anisotropy;
Textures_ModeChanged();
}
}
void Textures_setTextureComponents( GLint texture_components ){ void Textures_setTextureComponents( GLint texture_components ){
if ( g_texture_globals.texture_components != texture_components ) { if ( g_texture_globals.texture_components != texture_components ) {
Textures_Unrealise(); Textures_Unrealise();
@ -677,9 +683,6 @@ void TextureModeImport( ETexturesMode& self, int value ){
break; break;
case 5: case 5:
Textures_SetMode( eTextures_LINEAR_MIPMAP_LINEAR ); Textures_SetMode( eTextures_LINEAR_MIPMAP_LINEAR );
break;
case 6:
Textures_SetMode( eTextures_MAX_ANISOTROPY );
} }
} }
typedef ReferenceCaller1<ETexturesMode, int, TextureModeImport> TextureModeImportCaller; typedef ReferenceCaller1<ETexturesMode, int, TextureModeImport> TextureModeImportCaller;
@ -705,9 +708,6 @@ void TextureModeExport( ETexturesMode& self, const IntImportCallback& importer )
case eTextures_LINEAR_MIPMAP_LINEAR: case eTextures_LINEAR_MIPMAP_LINEAR:
importer( 5 ); importer( 5 );
break; break;
case eTextures_MAX_ANISOTROPY:
importer( 6 );
break;
default: default:
importer( 4 ); importer( 4 );
} }
@ -733,7 +733,7 @@ void Textures_constructPreferences( PreferencesPage& page ){
FloatExportCallback( FloatExportCaller( g_texture_globals.fGamma ) ) FloatExportCallback( FloatExportCaller( g_texture_globals.fGamma ) )
); );
{ {
const char* texture_mode[] = { "Nearest", "Nearest Mipmap", "Linear", "Bilinear", "Bilinear Mipmap", "Trilinear", "Anisotropy" }; const char* texture_mode[] = { "Nearest", "Nearest Mipmap", "Linear", "Bilinear", "Bilinear Mipmap", "Trilinear" };
page.appendCombo( page.appendCombo(
"Texture Render Mode", "Texture Render Mode",
STRING_ARRAY_RANGE( texture_mode ), STRING_ARRAY_RANGE( texture_mode ),
@ -762,6 +762,9 @@ void Textures_constructPreferences( PreferencesPage& page ){
IntExportCaller( reinterpret_cast<int&>( g_texture_globals.m_nTextureCompressionFormat ) ) IntExportCaller( reinterpret_cast<int&>( g_texture_globals.m_nTextureCompressionFormat ) )
); );
} }
page.appendCheckBox( "", "Anisotropy",
FreeCaller1<bool, Textures_SetAnisotropy>(),
BoolExportCaller( g_TextureAnisotropy ) );
} }
void Textures_constructPage( PreferenceGroup& group ){ void Textures_constructPage( PreferenceGroup& group ){
PreferencesPage page( group.createPage( "Textures", "Texture Settings" ) ); PreferencesPage page( group.createPage( "Textures", "Texture Settings" ) );
@ -783,6 +786,7 @@ void Textures_Construct(){
GlobalPreferenceSystem().registerPreference( "TextureCompressionFormat", TextureCompressionImportStringCaller(), IntExportStringCaller( reinterpret_cast<int&>( g_texture_globals.m_nTextureCompressionFormat ) ) ); GlobalPreferenceSystem().registerPreference( "TextureCompressionFormat", TextureCompressionImportStringCaller(), IntExportStringCaller( reinterpret_cast<int&>( g_texture_globals.m_nTextureCompressionFormat ) ) );
GlobalPreferenceSystem().registerPreference( "TextureFiltering", IntImportStringCaller( reinterpret_cast<int&>( g_texture_mode ) ), IntExportStringCaller( reinterpret_cast<int&>( g_texture_mode ) ) ); GlobalPreferenceSystem().registerPreference( "TextureFiltering", IntImportStringCaller( reinterpret_cast<int&>( g_texture_mode ) ), IntExportStringCaller( reinterpret_cast<int&>( g_texture_mode ) ) );
GlobalPreferenceSystem().registerPreference( "TextureAnisotropy", BoolImportStringCaller( g_TextureAnisotropy ), BoolExportStringCaller( g_TextureAnisotropy ) );
GlobalPreferenceSystem().registerPreference( "TextureQuality", IntImportStringCaller( g_Textures_textureQuality.m_latched ), IntExportStringCaller( g_Textures_textureQuality.m_latched ) ); GlobalPreferenceSystem().registerPreference( "TextureQuality", IntImportStringCaller( g_Textures_textureQuality.m_latched ), IntExportStringCaller( g_Textures_textureQuality.m_latched ) );
GlobalPreferenceSystem().registerPreference( "SI_Gamma", FloatImportStringCaller( g_texture_globals.fGamma ), FloatExportStringCaller( g_texture_globals.fGamma ) ); GlobalPreferenceSystem().registerPreference( "SI_Gamma", FloatImportStringCaller( g_texture_globals.fGamma ), FloatExportStringCaller( g_texture_globals.fGamma ) );