650 lines
24 KiB
C++
650 lines
24 KiB
C++
//**************************************************************
|
|
//* OpenGLide - Glide to OpenGL Wrapper
|
|
//* http://openglide.sourceforge.net
|
|
//*
|
|
//* OpenGL Extensions
|
|
//*
|
|
//* OpenGLide is OpenSource under LGPL license
|
|
//* Originaly made by Fabio Barros
|
|
//* Modified by Paul for Glidos (http://www.glidos.net)
|
|
//* Mac version and additional features by Jens-Olaf Hemprich
|
|
//**************************************************************
|
|
|
|
#include "Glide.h"
|
|
#include "GlideSettings.h"
|
|
#include "GLColorAlphaCombineEnvTables.h"
|
|
#include "GLextensions.h"
|
|
#include "GLRender.h"
|
|
#include "GLutil.h"
|
|
|
|
#include <agl.h>
|
|
|
|
|
|
enum enExtensionType
|
|
{
|
|
OGL_EXT_UNUSED = 0,
|
|
OGL_EXT_REQUIRED,
|
|
OGL_EXT_DESIRED
|
|
};
|
|
|
|
struct stExtensionSupport
|
|
{
|
|
char * name;
|
|
enExtensionType type;
|
|
bool * userVar;
|
|
bool * internalVar;
|
|
};
|
|
|
|
// Running in Classic ?
|
|
#ifdef OPENGLIDE_HOST_MAC
|
|
bool RunningInClassic = false;
|
|
#endif
|
|
|
|
// It is important that dummyExtVariable retains the value true, so
|
|
// we pass dummyExtVariable2 in places where the value may be altered.
|
|
bool dummyExtVariable = true;
|
|
bool dummyExtVariable2 = true;
|
|
|
|
// Env Combine fog data
|
|
static GLuint fogtexturename = 0;
|
|
static FxU8* fogalpharamp = NULL;
|
|
static GLint dummytexture = 0x00000000;
|
|
|
|
stExtensionSupport glNecessaryExt[] =
|
|
{
|
|
// new
|
|
{ "GL_EXT_abgr", OGL_EXT_REQUIRED, &dummyExtVariable, &dummyExtVariable2 },
|
|
{ "GL_EXT_bgra", OGL_EXT_REQUIRED, &dummyExtVariable, &dummyExtVariable2 },
|
|
{ "GL_EXT_secondary_color", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_secondary_color },
|
|
{ "GL_ARB_multitexture", OGL_EXT_DESIRED, &UserConfig.ARB_multitexture, &InternalConfig.ARB_multitexture },
|
|
{ "GL_ARB_texture_env_add", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_texture_env_add },
|
|
{ "GL_ARB_texture_env_combine", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_texture_env_combine },
|
|
{ "GL_ATI_texture_env_combine3", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.ATI_texture_env_combine3 },
|
|
{ "GL_EXT_texture_lod_bias", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_texture_lod_bias },
|
|
{ "GL_SGIS_generate_mipmap", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_SGIS_generate_mipmap },
|
|
{ "GL_SGIS_texture_edge_clamp", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_SGIS_texture_edge_clamp },
|
|
{ "GL_EXT_paletted_texture", OGL_EXT_DESIRED, &UserConfig.EXT_paletted_texture, &InternalConfig.EXT_paletted_texture },
|
|
{ "GL_APPLE_packed_pixels", OGL_EXT_REQUIRED, &dummyExtVariable, &dummyExtVariable2 },
|
|
{ "GL_APPLE_client_storage", OGL_EXT_DESIRED, &UserConfig.APPLE_client_storage, &InternalConfig.APPLE_client_storage },
|
|
{ "GL_EXT_compiled_vertex_array", OGL_EXT_DESIRED, &UserConfig.EXT_compiled_vertex_array,&InternalConfig.EXT_compiled_vertex_array },
|
|
{ "GL_ARB_texture_rectangle", OGL_EXT_DESIRED, &UserConfig.ARB_texture_rectangle, &InternalConfig.ARB_texture_rectangle },
|
|
#ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD
|
|
{ "GL_EXT_fog_coord", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_fog_coord },
|
|
#endif
|
|
#ifdef OPENGLIDE_SYSTEM_HAS_BLENDFUNC_SEPERATE
|
|
{ "GL_EXT_blend_func_separate", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_blend_func_separate },
|
|
#endif
|
|
{ "GL_EXT_texture_filter_anisotropic",OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.EXT_texture_filter_anisotropic },
|
|
{ "GL_ARB_multisample", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.ARB_multisample },
|
|
{ "GL_NV_multisample_filter_hint", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.NV_multisample_filter_hint },
|
|
{ "GL_EXT_clip_volume_hint", OGL_EXT_DESIRED, &UserConfig.EXT_clip_volume_hint, &InternalConfig.EXT_clip_volume_hint },
|
|
{ "GL_APPLE_transform_hint", OGL_EXT_DESIRED, &dummyExtVariable, &InternalConfig.APPLE_transform_hint },
|
|
{ "", OGL_EXT_UNUSED, &dummyExtVariable, &dummyExtVariable2 }
|
|
};
|
|
|
|
// check to see if Extension is Supported
|
|
// code by Mark J. Kilgard of NVidia modified by Fabio Barros
|
|
bool OGLIsExtensionSupported(const char* extensions, const char* extension)
|
|
{
|
|
char* where = (char *) strchr( extension, ' ' );
|
|
if ( where || ( *extension == '\0' ) )
|
|
{
|
|
return false;
|
|
}
|
|
const char* start = extensions;
|
|
if ( *start == '\0' )
|
|
{
|
|
GlideError( "No OpenGL extension supported, using all emulated.\n" );
|
|
return false;
|
|
}
|
|
|
|
while ( true )
|
|
{
|
|
where = (char *)strstr( start, extension );
|
|
if ( !where )
|
|
{
|
|
break;
|
|
}
|
|
const char* terminator = where + strlen( extension );
|
|
if ( ( where == start ) || ( *( where - 1 ) == ' ' ) )
|
|
{
|
|
if ( ( *terminator == ' ' ) || ( *terminator == '\0' ) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
start = terminator;
|
|
}
|
|
|
|
// fix for Rage 128 OpenGL Engine 1.1.ATI-5.99
|
|
// (See apple techote TN2014)
|
|
if (strcmp(extension, "GL_APPLE_packed_pixels") == 0)
|
|
{
|
|
return OGLIsExtensionSupported(extensions, "GL_APPLE_packed_pixel");
|
|
}
|
|
// fix for Rage 128 OpenGL Engine 1.1.ATI-5.99
|
|
// support for GL_EXT_texture_env_combine
|
|
else if (strcmp(extension, "GL_ARB_texture_env_combine") == 0)
|
|
{
|
|
return OGLIsExtensionSupported(extensions, "GL_EXT_texture_env_combine");
|
|
}
|
|
// also support the older GL_EXT_texture_env_add
|
|
else if (strcmp(extension, "GL_ARB_texture_env_add") == 0)
|
|
{
|
|
return OGLIsExtensionSupported(extensions, "GL_EXT_texture_env_add");
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void ValidateUserConfig( void )
|
|
{
|
|
glReportErrors("ValidateUserConfig");
|
|
|
|
// Copy config
|
|
InternalConfig = UserConfig;
|
|
|
|
GlideMsg( OGL_LOG_SEPARATE );
|
|
GlideMsg( "** OpenGL Information **\n" );
|
|
const unsigned char* renderer = glGetString( GL_RENDERER );
|
|
if (renderer == NULL || strlen(reinterpret_cast<const char*>(renderer)) == 0)
|
|
{
|
|
GlideError("The OpenGL driver failed to report its version/vendor/renderer.\nThis may be caused by beta drivers located in thge game directory.\nThese drivers should be deleted.\n");
|
|
}
|
|
GlideMsg( OGL_LOG_SEPARATE );
|
|
GlideMsg( "Vendor: %s\n", glGetString( GL_VENDOR ) );
|
|
GlideMsg( "Renderer: %s\n", glGetString( GL_RENDERER ) );
|
|
GlideMsg( "Version: %s\n", glGetString( GL_VERSION ) );
|
|
// Extension string is too long for the temp buffer, so we don't use GlideMsg()
|
|
UserConfig.write_log("Available Extensions: ");
|
|
const char* extensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
|
UserConfig.write_log(extensions);
|
|
UserConfig.write_log("\n");
|
|
|
|
GlideMsg( OGL_LOG_SEPARATE );
|
|
GlideMsg( "OpenGL Extensions:\n" );
|
|
GlideMsg( OGL_LOG_SEPARATE );
|
|
int index = 0;
|
|
while ( strlen( glNecessaryExt[ index ].name ) > 0 )
|
|
{
|
|
*glNecessaryExt[ index ].internalVar = false;
|
|
switch ( glNecessaryExt[ index ].type )
|
|
{
|
|
case OGL_EXT_REQUIRED:
|
|
if (!OGLIsExtensionSupported(extensions, glNecessaryExt[index].name ))
|
|
{
|
|
char buffer[StringBufferSize];
|
|
sprintf(buffer, "Severe Problem: OpenGL %s extension is required for %s!",
|
|
glNecessaryExt[ index ].name, OpenGLideProductName);
|
|
GlideError(buffer);
|
|
}
|
|
break;
|
|
case OGL_EXT_DESIRED:
|
|
if (!OGLIsExtensionSupported(extensions, glNecessaryExt[index].name))
|
|
{
|
|
char buffer[StringBufferSize];
|
|
sprintf(buffer, "Note: OpenGL %s extension is not supported, emulating behavior.\n",
|
|
glNecessaryExt[ index ].name );
|
|
GlideMsg(buffer);
|
|
}
|
|
else
|
|
{
|
|
if ( *glNecessaryExt[ index ].userVar )
|
|
{
|
|
*glNecessaryExt[ index ].internalVar = true;
|
|
GlideMsg( "Extension %s is present and ENABLED\n", glNecessaryExt[ index ].name );
|
|
}
|
|
else
|
|
{
|
|
char buffer[StringBufferSize];
|
|
sprintf(buffer, "Note: OpenGL %s extension is supported but disabled by user\n",
|
|
glNecessaryExt[ index ].name );
|
|
GlideMsg(buffer);
|
|
}
|
|
}
|
|
break;
|
|
case OGL_EXT_UNUSED:
|
|
break;
|
|
}
|
|
++index;
|
|
}
|
|
GlideMsg( OGL_LOG_SEPARATE );
|
|
GLExtensions( );
|
|
}
|
|
|
|
void GLExtensions(void)
|
|
{
|
|
glReportErrors("GLExtensions");
|
|
const float one = 1.0f;
|
|
|
|
#ifdef OPENGLIDE_HOST_MAC
|
|
RunningInClassic = strstr(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)), "GL_EXT_fog_coord") != NULL;
|
|
#endif
|
|
|
|
GlideMsg("OpenGL configuration:\n");
|
|
GlideMsg(OGL_LOG_SEPARATE);
|
|
|
|
// query the actual buffer size
|
|
GLint size;
|
|
glGetIntegerv(GL_DEPTH_BITS, &size);
|
|
glReportError();
|
|
GlideMsg("Depthbuffer size = %d\n", size);
|
|
// Rendering quality seems to be better when this is left enabled for depth buffer size < 24 bits only
|
|
// (Try spinning around at the portal in the first level of Tomb Raider Gold)
|
|
const int disablePrecisionFixAtDepthSize = 24;
|
|
if (size >= disablePrecisionFixAtDepthSize && InternalConfig.PrecisionFix == 1)
|
|
{
|
|
GlideMsg("Actual number of depthbuffer bits is >= %d - precision fix can safely be disabled\n", disablePrecisionFixAtDepthSize, size);
|
|
InternalConfig.PrecisionFix = 0;
|
|
}
|
|
if (UserConfig.GapFix & OpenGLideGapFixFlag_Enabled)
|
|
{
|
|
glGetIntegerv(GL_STENCIL_BITS, &size);
|
|
GlideMsg("Stencilbuffer size = %d\n", size);
|
|
}
|
|
GLint MaxAnisotropyLevel;
|
|
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &MaxAnisotropyLevel);
|
|
GlideMsg("Maximum level of anisotropy = %d\n", MaxAnisotropyLevel);
|
|
|
|
// Since this a global setting, texture data must not be uploaded from temp buffers
|
|
if (InternalConfig.APPLE_client_storage)
|
|
{
|
|
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, true);
|
|
glReportError();
|
|
}
|
|
// Anisotropic filtering
|
|
if (InternalConfig.EXT_texture_filter_anisotropic)
|
|
{
|
|
GLint MaxAnisotropyLevel;
|
|
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &MaxAnisotropyLevel);
|
|
if (UserConfig.AnisotropylLevel > MaxAnisotropyLevel)
|
|
{
|
|
InternalConfig.AnisotropylLevel = MaxAnisotropyLevel;
|
|
}
|
|
else
|
|
{
|
|
InternalConfig.AnisotropylLevel = UserConfig.AnisotropylLevel;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
InternalConfig.AnisotropylLevel = 1;
|
|
}
|
|
|
|
if (InternalConfig.ARB_multisample == false)
|
|
{
|
|
InternalConfig.FullSceneAntiAliasing = 0;
|
|
}
|
|
else if (InternalConfig.FullSceneAntiAliasing > 0)
|
|
{
|
|
// Thanks to Frank Condello <developerNOSPAM@NOSPAMchaoticbox.com> for posting this trick at
|
|
// http://support.realsoftware.com/listarchives/realbasic-games/2004-09/msg00273.html
|
|
aglSetInteger(pWindowInfo->aglContext, AGL_ATI_FSAA_LEVEL, reinterpret_cast<const long*>(&InternalConfig.FullSceneAntiAliasing));
|
|
GLenum err = aglGetError();
|
|
if (AGL_NO_ERROR != err)
|
|
{
|
|
GlideError("Couldn't set ATI FSAA level: %s\n", reinterpret_cast<const char *>(aglErrorString(err)));
|
|
}
|
|
// Initially enable multisampling
|
|
glEnable(GL_MULTISAMPLE_ARB);
|
|
glReportError();
|
|
}
|
|
if (InternalConfig.FullSceneAntiAliasing > 0
|
|
&& InternalConfig.NV_multisample_filter_hint)
|
|
{
|
|
glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
|
|
glReportError();
|
|
}
|
|
|
|
#ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD
|
|
if (InternalConfig.EXT_fog_coord == false && InternalConfig.FogMode > OpenGLideFogEmulation_EnvCombine)
|
|
{
|
|
InternalConfig.FogMode = OpenGLideFogEmulation_EnvCombine;
|
|
}
|
|
#endif
|
|
|
|
// FogCoord extension not supported on MacOS9
|
|
#ifdef OPENGLIDE_SYSTEM_DOESN_T_HAVE_FOGCOORD
|
|
if (InternalConfig.FogMode > OpenGLideFogEmulation_EnvCombine)
|
|
{
|
|
InternalConfig.FogMode = OpenGLideFogEmulation_EnvCombine;
|
|
}
|
|
#endif
|
|
|
|
// check for other extensions needed by fog emulation
|
|
if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine
|
|
&& InternalConfig.EXT_texture_env_combine == false)
|
|
{
|
|
GlideMsg( "Enhanced fog emulation disabled because GL_ARB_texture_env_combine is missing or disabled\n");
|
|
InternalConfig.FogMode = OpenGLideFogEmulation_Simple;
|
|
}
|
|
else if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine
|
|
&& InternalConfig.ARB_multitexture == false)
|
|
{
|
|
GlideMsg( "Enhanced fog emulation disabled because GL_ARB_multitexture is missing or disabled\n");
|
|
InternalConfig.FogMode = OpenGLideFogEmulation_Simple;
|
|
}
|
|
|
|
// Setup texture units
|
|
if (InternalConfig.GlideTextureUnits > 1)
|
|
{
|
|
GlideMsg( "Only one texure unit is currently supported. Additional units are ignored.\n");
|
|
}
|
|
if (InternalConfig.ARB_multitexture)
|
|
{
|
|
GLint number_of_texture_units = 1;
|
|
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &number_of_texture_units);
|
|
GlideMsg("MultiTexture Units = %x\n", number_of_texture_units);
|
|
if (InternalConfig.ColorAlphaRenderMode >= OpenGLideColorAlphaRenderMode_Unknown)
|
|
{
|
|
InternalConfig.ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_Automatic;
|
|
}
|
|
if (InternalConfig.ColorAlphaRenderMode > OpenGLideColorAlphaRenderMode_Simple
|
|
&& InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine
|
|
&& number_of_texture_units <= 2)
|
|
{
|
|
GlideMsg( "Coloralpha render mode reset to simple in favour of enhanced fog emulation\n");
|
|
InternalConfig.ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_Simple;
|
|
}
|
|
// Setup coloralpha texture units
|
|
OpenGL.ColorAlphaUnit1 = GL_TEXTURE0_ARB;
|
|
if ((number_of_texture_units > 2 && InternalConfig.EXT_texture_env_combine
|
|
|| number_of_texture_units == 2 && InternalConfig.FogMode != OpenGLideFogEmulation_EnvCombine)
|
|
&& (InternalConfig.ColorAlphaRenderMode == OpenGLideColorAlphaRenderMode_Automatic
|
|
|| InternalConfig.ColorAlphaRenderMode > OpenGLideColorAlphaRenderMode_Simple))
|
|
{
|
|
OpenGL.ColorAlphaUnit2 = GL_TEXTURE1_ARB;
|
|
OpenGL.FogTextureUnit = GL_TEXTURE2_ARB;
|
|
// All texture units are enabled all the time
|
|
glActiveTextureARB(OpenGL.ColorAlphaUnit1);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
|
|
glActiveTextureARB(OpenGL.ColorAlphaUnit2);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
|
|
glReportError();
|
|
// Secondary color not neded in the enhanced color alpha rendering model
|
|
InternalConfig.EXT_secondary_color = false;
|
|
if (InternalConfig.ColorAlphaRenderMode == OpenGLideColorAlphaRenderMode_Automatic)
|
|
{
|
|
if (InternalConfig.ATI_texture_env_combine3)
|
|
{
|
|
// With GL_ATI_texture_env_combine3, more combine functions can be modeled as
|
|
// exactly as the original combine functions. They can also be rendered more
|
|
// often with one texture unit, which leaves more space for correct rendering
|
|
// of textures that use both chromakeying and alpha blending together.
|
|
InternalConfig.ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_EnvCombine3_ATI;
|
|
OpenGL.ColorCombineFunctions = ColorCombineFunctionsEnvCombine3ATI;
|
|
OpenGL.AlphaCombineFunctions = AlphaCombineFunctionsEnvCombine3ATI;
|
|
}
|
|
else if (InternalConfig.EXT_texture_env_combine)
|
|
{
|
|
// Standard setup, works with most graphics cards and provides accurate
|
|
// results in most cases
|
|
InternalConfig.ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_EnvCombine_ARB;
|
|
OpenGL.ColorCombineFunctions = ColorCombineFunctionsEnvCombineARB;
|
|
OpenGL.AlphaCombineFunctions = AlphaCombineFunctionsEnvCombineARB;
|
|
}
|
|
}
|
|
if (InternalConfig.ColorAlphaRenderMode == OpenGLideColorAlphaRenderMode_EnvCombine3_ATI)
|
|
{
|
|
OpenGL.ColorCombineFunctions = ColorCombineFunctionsEnvCombine3ATI;
|
|
OpenGL.AlphaCombineFunctions = AlphaCombineFunctionsEnvCombine3ATI;
|
|
}
|
|
else if (InternalConfig.ColorAlphaRenderMode == OpenGLideColorAlphaRenderMode_EnvCombine_ARB)
|
|
{
|
|
OpenGL.ColorCombineFunctions = ColorCombineFunctionsEnvCombineARB;
|
|
OpenGL.AlphaCombineFunctions = AlphaCombineFunctionsEnvCombineARB;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OpenGL.ColorAlphaUnit2 = 0;
|
|
OpenGL.FogTextureUnit = number_of_texture_units > 2 ? GL_TEXTURE2_ARB : GL_TEXTURE1_ARB;
|
|
InternalConfig.ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_Simple;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OpenGL.ColorAlphaUnit1 = GL_TEXTURE0_ARB;
|
|
OpenGL.ColorAlphaUnit2 = 0;
|
|
OpenGL.FogTextureUnit = 0;
|
|
InternalConfig.ColorAlphaRenderMode = OpenGLideColorAlphaRenderMode_Simple;
|
|
}
|
|
|
|
// Print out coloralpha render mode
|
|
char* coloralpharendermodename;
|
|
switch (InternalConfig.ColorAlphaRenderMode)
|
|
{
|
|
case OpenGLideColorAlphaRenderMode_Simple:
|
|
coloralpharendermodename = "MultiTextureSimple";
|
|
break;
|
|
case OpenGLideColorAlphaRenderMode_EnvCombine_ARB:
|
|
coloralpharendermodename = "EnvironmentCombineARB";
|
|
break;
|
|
case OpenGLideColorAlphaRenderMode_EnvCombine3_ATI:
|
|
coloralpharendermodename = "EnvironmentCombine3ATI";
|
|
break;
|
|
default:
|
|
assert(false);
|
|
break;
|
|
}
|
|
GlideMsg( "Coloralpha rendermode = %s\n", coloralpharendermodename);
|
|
|
|
if (OpenGL.FogTextureUnit == 0 && InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine)
|
|
{
|
|
InternalConfig.FogMode = OpenGLideFogEmulation_Simple;
|
|
}
|
|
|
|
if (InternalConfig.EXT_secondary_color && OpenGL.ColorAlphaUnit2 == 0)
|
|
{
|
|
glEnable(GL_COLOR_SUM_EXT);
|
|
glReportError();
|
|
}
|
|
|
|
if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine)
|
|
{
|
|
fogalpharamp = static_cast<unsigned char*> (AllocBuffer(256, 1));
|
|
if (fogalpharamp)
|
|
{
|
|
for(unsigned int i = 0; i < 256; i++)
|
|
{
|
|
fogalpharamp[i] = 255 - i;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
InternalConfig.FogMode = OpenGLideFogEmulation_Simple;
|
|
}
|
|
}
|
|
|
|
if (OpenGL.ColorAlphaUnit2 || InternalConfig.FogMode != OpenGLideFogEmulation_EnvCombine)
|
|
{
|
|
glGenTextures(1, &OpenGL.DummyTextureName);
|
|
glPrioritizeTextures(1, &OpenGL.DummyTextureName, &one);
|
|
glActiveTextureARB(OpenGL.ColorAlphaUnit1);
|
|
glBindTexture(GL_TEXTURE_2D, OpenGL.DummyTextureName);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, InternalConfig.EXT_SGIS_texture_edge_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP); // GL_REPEAT would cause randomly
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, InternalConfig.EXT_SGIS_texture_edge_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP); // fogged triangles in the foreground
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
if (InternalConfig.AnisotropylLevel >= 2)
|
|
{
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
|
|
}
|
|
glTexImage2D(GL_TEXTURE_2D, 0, 4, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &dummytexture);
|
|
glReportError();
|
|
}
|
|
|
|
#ifdef OPENGLIDE_SYSTEM_HAS_FOGCOORD
|
|
if (InternalConfig.FogMode == OpenGLideFogEmulation_FogCoord)
|
|
{
|
|
glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
|
|
glFogf(GL_FOG_MODE, GL_LINEAR);
|
|
glFogf(GL_FOG_START, 0.0f);
|
|
glFogf(GL_FOG_END, 1.0f);
|
|
glReportError();
|
|
}
|
|
else
|
|
#endif
|
|
if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine)
|
|
{
|
|
GrFog_t fogtable[GR_FOG_TABLE_SIZE];
|
|
guFogGenerateLinear(fogtable, 0.0f, 1.0f);
|
|
grFogTable(fogtable);
|
|
GlideMsg( "Using env-combine fog emulation\n");
|
|
// Setup fog texture unit
|
|
glActiveTextureARB(OpenGL.FogTextureUnit);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
|
|
// The color part is used for the fog function (see RenderUpdateState.cpp)
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_TEXTURE);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
|
|
// The alpha is not blended with the fog alpha because this
|
|
// would also fog otherwise invisible parts of the texture
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
|
|
glGenTextures(1, &fogtexturename);
|
|
glPrioritizeTextures(1, &fogtexturename, &one);
|
|
glBindTexture(GL_TEXTURE_2D, fogtexturename);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, InternalConfig.EXT_SGIS_texture_edge_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP); // GL_REPEAT would cause randomly
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, InternalConfig.EXT_SGIS_texture_edge_clamp ? GL_CLAMP_TO_EDGE : GL_CLAMP); // fogged triangles in the foreground
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
if (InternalConfig.AnisotropylLevel >= 2)
|
|
{
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
|
|
}
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 256, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, fogalpharamp);
|
|
glReportError();
|
|
}
|
|
else if (InternalConfig.FogMode == OpenGLideFogEmulation_Simple)
|
|
{
|
|
// Provide a reasonable default for application that use fog,
|
|
// but don't set the fog table (like Carmageddon)
|
|
// Adjusted to camageddon Main Street Track (compared with Race Track Preview image)
|
|
// and to Coastal Carnage Track so that objects become colored right after they pop up
|
|
// when popup distance option is far (fog is set to black in this level)
|
|
|
|
// This doesn't seem to work with MacOS9 OpenGL drivers (beasue of version < 1.3 ?).
|
|
// The whole scene is too dark. However, it works well in the Classic environment
|
|
// (which actually uses the OpenGL driver provided by MacOS X)
|
|
|
|
// When the fog table is not set as below, the whole scene seems to be a little to dark,
|
|
// whereas when it's set, the foreground looks as brighht as in the software rendrerer.
|
|
|
|
GrFog_t fogtable[GR_FOG_TABLE_SIZE];
|
|
// The values below come from comparing screenshots between GeForce 2mx
|
|
// (MacOS X OpenGL 1.3 driver) and the software renderer version of Carmageddon
|
|
guFogGenerateLinear(fogtable, 0.9985f, 1.0f);
|
|
grFogTable(fogtable);
|
|
GlideMsg( "Using simple fog emulation\n");
|
|
}
|
|
else
|
|
{
|
|
InternalConfig.FogMode = OpenGLideFogEmulation_None;
|
|
// These default values must be provied even if fog is
|
|
// disabled or the shadows in Carmageddon Splatpack,
|
|
// Meltdown Alley level will have the fog color
|
|
// (occures on MacOS 9, Nvidia OpenGL 1.22)
|
|
glFogf( GL_FOG_MODE, GL_LINEAR );
|
|
glReportError();
|
|
glFogf( GL_FOG_START, 1.0f );
|
|
glReportError();
|
|
glFogf( GL_FOG_END, 0.0f );
|
|
glReportError();
|
|
glDisable(GL_FOG);
|
|
GlideMsg( "Fog emulation disabled\n");
|
|
}
|
|
|
|
if (InternalConfig.FogMode != OpenGLideFogEmulation_EnvCombine && OpenGL.DummyTextureName && OpenGL.FogTextureUnit)
|
|
{
|
|
// Setup fog texture unit as inverter (for inverting the color alpha output)
|
|
glActiveTextureARB(OpenGL.FogTextureUnit);
|
|
glBindTexture(GL_TEXTURE_2D, OpenGL.DummyTextureName);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
|
|
glReportError();
|
|
OpenGL.FogTextureUnitEnabledState = true;
|
|
}
|
|
else
|
|
{
|
|
OpenGL.FogTextureUnitEnabledState = false;
|
|
}
|
|
// End of texture unit setup
|
|
glActiveTextureARB(OpenGL.ColorAlphaUnit1);
|
|
|
|
if (InternalConfig.EXT_paletted_texture)
|
|
{
|
|
GlideMsg( "Using Palette Extension\n" );
|
|
}
|
|
|
|
#ifdef OPENGLIDE_HOST_MAC
|
|
if (InternalConfig.EXT_compiled_vertex_array)
|
|
{
|
|
// Compiled vertex array crashes on MacOS9 (at least on my system)
|
|
// so if anybody who would like to investigate this...
|
|
if (!RunningInClassic)
|
|
{
|
|
InternalConfig.EXT_compiled_vertex_array = false;
|
|
GlideMsg( "Compiled vertex arrays have been disabled (works in Classic only)\n" );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (InternalConfig.TextureSmoothing)
|
|
{
|
|
OpenGL.MinFilterMode = InternalConfig.Mipmapping ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
|
|
OpenGL.MagFilterMode = GL_LINEAR;
|
|
}
|
|
|
|
if (InternalConfig.EXT_clip_volume_hint)
|
|
{
|
|
glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST);
|
|
OpenGL.ClipVerticesEnabledState = false;
|
|
}
|
|
|
|
if (InternalConfig.APPLE_transform_hint)
|
|
{
|
|
glHint(GL_TRANSFORM_HINT_APPLE, GL_NICEST);
|
|
}
|
|
|
|
if (InternalConfig.EXT_SGIS_generate_mipmap)
|
|
{
|
|
glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
|
|
}
|
|
|
|
VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1);
|
|
}
|
|
|
|
void GLExtensionsCleanup()
|
|
{
|
|
// cleanup fog texture
|
|
if (InternalConfig.FogMode == OpenGLideFogEmulation_EnvCombine)
|
|
{
|
|
if (fogalpharamp)
|
|
{
|
|
FreeBuffer(fogalpharamp);
|
|
glReportErrors("RenderFree");
|
|
glDeleteTextures(1, &fogtexturename);
|
|
glReportError();
|
|
}
|
|
}
|
|
if (OpenGL.DummyTextureName)
|
|
{
|
|
glDeleteTextures(1, &OpenGL.DummyTextureName);
|
|
}
|
|
}
|