From aecdd9b4c5b6c78792290aef6bc740827cf02680 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 13 Sep 2019 21:43:05 +0200 Subject: [PATCH] - this is the state I want to build. --- platform/Windows/props/build_common.props | 2 +- source/build/src/mdsprite.cpp | 2 +- source/build/src/polymer.cpp | 6336 --------------------- source/build/src/polymost.cpp | 1109 +--- source/build/src/sdlayer.cpp | 16 +- source/build/src/texcache.cpp | 25 +- source/build/src/winbits.cpp | 80 +- 7 files changed, 183 insertions(+), 7387 deletions(-) diff --git a/platform/Windows/props/build_common.props b/platform/Windows/props/build_common.props index e78e9dfd1..649af037e 100644 --- a/platform/Windows/props/build_common.props +++ b/platform/Windows/props/build_common.props @@ -5,7 +5,7 @@ - _CRT_SECURE_NO_WARNINGS;WIN32;RENDERTYPESDL=1;MIXERTYPEWIN=1;SDL_USEFOLDER;SDL_TARGET=2;USE_OPENGL=1;POLYMER=1;STARTUP_WINDOW;USE_LIBVPX;HAVE_VORBIS;HAVE_XMP;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;RENDERTYPESDL=1;MIXERTYPEWIN=1;SDL_USEFOLDER;SDL_TARGET=2;USE_OPENGL=1;STARTUP_WINDOW;USE_LIBVPX;HAVE_VORBIS;HAVE_XMP;%(PreprocessorDefinitions) ./include;./include/vpx/;./include/sdl2/;../../source/build/include;../../source/mact/include;../../source/audiolib/include;../../source/enet/include;../../source/glad/include;../../source/libxmp-lite/include;../../source/libxmp-lite/include/libxmp-lite 4996;4244;4018;4267 /J %(AdditionalOptions) diff --git a/source/build/src/mdsprite.cpp b/source/build/src/mdsprite.cpp index 630ad89de..f0fcda732 100644 --- a/source/build/src/mdsprite.cpp +++ b/source/build/src/mdsprite.cpp @@ -902,7 +902,7 @@ int32_t mdloadskin(md2model_t *m, int32_t number, int32_t pal, int32_t surf) if (pal < (MAXPALOOKUPS - RESERVEDPALS)) m->usesalpha = hasalpha; if ((doalloc&3)==1) - glGenTextures(1, texidx); + GetTextureHandle(texidx); glBindTexture(GL_TEXTURE_2D, *texidx); diff --git a/source/build/src/polymer.cpp b/source/build/src/polymer.cpp index f0b8222af..e69de29bb 100644 --- a/source/build/src/polymer.cpp +++ b/source/build/src/polymer.cpp @@ -1,6336 +0,0 @@ -// blah - -#if defined USE_OPENGL && defined POLYMER - -#include "compat.h" - -#define POLYMER_C -#include "polymer.h" -#include "engine_priv.h" -#include "xxhash.h" -#include "texcache.h" - -// CVARS -int32_t pr_lighting = 1; -int32_t pr_normalmapping = 1; -int32_t pr_specularmapping = 1; -int32_t pr_shadows = 1; -int32_t pr_shadowcount = 5; -int32_t pr_shadowdetail = 4; -int32_t pr_shadowfiltering = 1; -int32_t pr_maxlightpasses = 10; -int32_t pr_maxlightpriority = PR_MAXLIGHTPRIORITY; -int32_t pr_fov = 512; -double pr_customaspect = 0.0f; -int32_t pr_billboardingmode = 1; -int32_t pr_verbosity = 1; // 0: silent, 1: errors and one-times, 2: multiple-times, 3: flood -int32_t pr_wireframe = 0; -int32_t pr_vbos = 2; -int32_t pr_buckets = 0; -int32_t pr_gpusmoothing = 1; -int32_t pr_overrideparallax = 0; -float pr_parallaxscale = 0.1f; -float pr_parallaxbias = 0.0f; -int32_t pr_overridespecular = 0; -float pr_specularpower = 15.0f; -float pr_specularfactor = 1.0f; -int32_t pr_highpalookups = 1; -int32_t pr_artmapping = 1; -int32_t pr_overridehud = 0; -float pr_hudxadd = 0.0f; -float pr_hudyadd = 0.0f; -float pr_hudzadd = 0.0f; -int32_t pr_hudangadd = 0; -int32_t pr_hudfov = 512; -float pr_overridemodelscale = 0.0f; -int32_t pr_ati_fboworkaround = 0; -int32_t pr_ati_nodepthoffset = 0; -#ifdef __APPLE__ -int32_t pr_ati_textureformat_one = 0; -#endif -int32_t pr_nullrender = 0; // 1: no draw, 2: no draw or updates - -int32_t r_pr_maxlightpasses = 5; // value of the cvar (not live value), used to detect changes - -GLenum mapvbousage = GL_STREAM_DRAW; -GLenum modelvbousage = GL_STATIC_DRAW; - -// BUILD DATA -_prsector *prsectors[MAXSECTORS]; -_prwall *prwalls[MAXWALLS]; -_prsprite *prsprites[MAXSPRITES]; -_prmaterial mdspritematerial; -_prhighpalookup prhighpalookups[MAXBASEPALS][MAXPALOOKUPS]; - -// One U8 texture per tile -GLuint prartmaps[MAXTILES]; -// 256 U8U8U8 values per basepal -GLuint prbasepalmaps[MAXBASEPALS]; -// numshades full indirections (32*256) per lookup -GLuint prlookups[MAXPALOOKUPS]; - -GLuint prmapvbo; -const GLsizeiptr proneplanesize = sizeof(_prvert) * 4; -const GLintptr prwalldatasize = sizeof(_prvert)* 4 * 3; // wall, over and mask planes for every wall -GLintptr prwalldataoffset; - -GLuint prindexringvbo; -GLuint *prindexring; -const GLsizeiptr prindexringsize = 65535; -GLintptr prindexringoffset; - -const GLbitfield prindexringmapflags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT; - -_prbucket *prbuckethead; -int32_t prcanbucket; - -static const _prvert vertsprite[4] = -{ - { - -0.5f, 0.0f, 0.0f, - 0.0f, 1.0f, - 0xff, 0xff, 0xff, 0xff, - }, - { - 0.5f, 0.0f, 0.0f, - 1.0f, 1.0f, - 0xff, 0xff, 0xff, 0xff, - }, - { - 0.5f, 1.0f, 0.0f, - 1.0f, 0.0f, - 0xff, 0xff, 0xff, 0xff, - }, - { - -0.5f, 1.0f, 0.0f, - 0.0f, 0.0f, - 0xff, 0xff, 0xff, 0xff, - }, -}; - -static const _prvert horizsprite[4] = -{ - { - -0.5f, 0.0f, 0.5f, - 0.0f, 0.0f, - 0xff, 0xff, 0xff, 0xff, - }, - { - 0.5f, 0.0f, 0.5f, - 1.0f, 0.0f, - 0xff, 0xff, 0xff, 0xff, - }, - { - 0.5f, 0.0f, -0.5f, - 1.0f, 1.0f, - 0xff, 0xff, 0xff, 0xff, - }, - { - -0.5f, 0.0f, -0.5f, - 0.0f, 1.0f, - 0xff, 0xff, 0xff, 0xff, - }, -}; - -static const GLfloat skyboxdata[4 * 5 * 6] = -{ - // -ZY - -0.5f, -0.5f, 0.5f, - 0.0f, 1.0f, - -0.5f, -0.5f, -0.5f, - 1.0f, 1.0f, - -0.5f, 0.5f, -0.5f, - 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, - 0.0f, 0.0f, - - // XY - -0.5f, -0.5f, -0.5f, - 0.0f, 1.0f, - 0.5f, -0.5f, -0.5f, - 1.0f, 1.0f, - 0.5f, 0.5f, -0.5f, - 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, - 0.0f, 0.0f, - - // ZY - 0.5f, -0.5f, -0.5f, - 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, - 1.0f, 1.0f, - 0.5f, 0.5f, 0.5f, - 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, - 0.0f, 0.0f, - - // -XY - 0.5f, -0.5f, 0.5f, - 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, - 1.0f, 1.0f, - -0.5f, 0.5f, 0.5f, - 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, - 0.0f, 0.0f, - - // XZ - -0.5f, 0.5f, -0.5f, - 1.0f, 1.0f, - 0.5f, 0.5f, -0.5f, - 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, - 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, - 0.0f, 1.0f, - - // X-Z - -0.5f, -0.5f, 0.5f, - 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, - 0.0f, 1.0f, - 0.5f, -0.5f, -0.5f, - 1.0f, 1.0f, - -0.5f, -0.5f, -0.5f, - 1.0f, 0.0f, -}; - -GLuint skyboxdatavbo; - -GLfloat artskydata[16]; - -// LIGHTS -static _prplanelist *plpool; -#pragma pack(push,1) -_prlight prlights[PR_MAXLIGHTS]; -int32_t lightcount; -int32_t curlight; -#pragma pack(pop) - -static const GLfloat shadowBias[] = -{ - 0.5, 0.0, 0.0, 0.0, - 0.0, 0.5, 0.0, 0.0, - 0.0, 0.0, 0.5, 0.0, - 0.5, 0.5, 0.5, 1.0 -}; - -// MATERIALS -static const _prprogrambit prprogrambits[PR_BIT_COUNT] = { - { - 1 << PR_BIT_HEADER, - // vert_def - "#version 120\n" - "#extension GL_ARB_texture_rectangle : enable\n" - "\n", - // vert_prog - "", - // frag_def - "#version 120\n" - "#extension GL_ARB_texture_rectangle : enable\n" - "\n", - // frag_prog - "", - }, - { - 1 << PR_BIT_ANIM_INTERPOLATION, - // vert_def - "attribute vec4 nextFrameData;\n" - "attribute vec4 nextFrameNormal;\n" - "uniform float frameProgress;\n" - "\n", - // vert_prog - " vec4 currentFramePosition;\n" - " vec4 nextFramePosition;\n" - "\n" - " currentFramePosition = curVertex * (1.0 - frameProgress);\n" - " nextFramePosition = nextFrameData * frameProgress;\n" - " curVertex = currentFramePosition + nextFramePosition;\n" - "\n" - " currentFramePosition = vec4(curNormal, 1.0) * (1.0 - frameProgress);\n" - " nextFramePosition = nextFrameNormal * frameProgress;\n" - " curNormal = vec3(currentFramePosition + nextFramePosition);\n" - "\n", - // frag_def - "", - // frag_prog - "", - }, - { - 1 << PR_BIT_LIGHTING_PASS, - // vert_def - "", - // vert_prog - "", - // frag_def - "", - // frag_prog - " isLightingPass = 1;\n" - " result = vec4(0.0, 0.0, 0.0, 1.0);\n" - "\n", - }, - { - 1 << PR_BIT_NORMAL_MAP, - // vert_def - "attribute vec3 T;\n" - "attribute vec3 B;\n" - "attribute vec3 N;\n" - "uniform vec3 eyePosition;\n" - "varying vec3 tangentSpaceEyeVec;\n" - "\n", - // vert_prog - " TBN = mat3(T, B, N);\n" - " tangentSpaceEyeVec = eyePosition - vec3(curVertex);\n" - " tangentSpaceEyeVec = TBN * tangentSpaceEyeVec;\n" - "\n" - " isNormalMapped = 1;\n" - "\n", - // frag_def - "uniform sampler2D normalMap;\n" - "uniform vec2 normalBias;\n" - "varying vec3 tangentSpaceEyeVec;\n" - "\n", - // frag_prog - " vec4 normalStep;\n" - " float biasedHeight;\n" - "\n" - " eyeVec = normalize(tangentSpaceEyeVec);\n" - "\n" - " for (int i = 0; i < 4; i++) {\n" - " normalStep = texture2D(normalMap, commonTexCoord.st);\n" - " biasedHeight = normalStep.a * normalBias.x - normalBias.y;\n" - " commonTexCoord += (biasedHeight - commonTexCoord.z) * normalStep.z * eyeVec;\n" - " }\n" - "\n" - " normalTexel = texture2D(normalMap, commonTexCoord.st);\n" - "\n" - " isNormalMapped = 1;\n" - "\n", - }, - { - 1 << PR_BIT_ART_MAP, - // vert_def - "varying vec3 horizDistance;\n" - "\n", - // vert_prog - " gl_TexCoord[0] = gl_MultiTexCoord0;\n" - " horizDistance = vec3(gl_ModelViewMatrix * curVertex);\n" - "\n", - // frag_def - "uniform sampler2D artMap;\n" - "uniform sampler2D basePalMap;\n" - "uniform sampler2DRect lookupMap;\n" - "uniform float shadeOffset;\n" - "uniform float visibility;\n" - "varying vec3 horizDistance;\n" - "\n", - // frag_prog - - " float shadeLookup = length(horizDistance) / 1.024 * visibility;\n" - " shadeLookup = shadeLookup + shadeOffset;\n" - "\n" - " float colorIndex = texture2D(artMap, commonTexCoord.st).r * 256.0;\n" - " float colorIndexNear = texture2DRect(lookupMap, vec2(colorIndex, floor(shadeLookup))).r;\n" - " float colorIndexFar = texture2DRect(lookupMap, vec2(colorIndex, floor(shadeLookup + 1.0))).r;\n" - " float colorIndexFullbright = texture2DRect(lookupMap, vec2(colorIndex, 0.0)).r;\n" - "\n" - " vec3 texelNear = texture2D(basePalMap, vec2(colorIndexNear, 0.5)).rgb;\n" - " vec3 texelFar = texture2D(basePalMap, vec2(colorIndexFar, 0.5)).rgb;\n" - " diffuseTexel.rgb = texture2D(basePalMap, vec2(colorIndexFullbright, 0.5)).rgb;\n" - "\n" - " if (isLightingPass == 0) {\n" - " result.rgb = mix(texelNear, texelFar, fract(shadeLookup));\n" - " result.a = 1.0;\n" - " if (colorIndex == 256.0)\n" - " result.a = 0.0;\n" - " }\n" - "\n", - }, - { - 1 << PR_BIT_DIFFUSE_MAP, - // vert_def - "uniform vec2 diffuseScale;\n" - "\n", - // vert_prog - " gl_TexCoord[0] = vec4(diffuseScale, 1.0, 1.0) * gl_MultiTexCoord0;\n" - "\n", - // frag_def - "uniform sampler2D diffuseMap;\n" - "\n", - // frag_prog - " diffuseTexel = texture2D(diffuseMap, commonTexCoord.st);\n" - "\n", - }, - { - 1 << PR_BIT_DIFFUSE_DETAIL_MAP, - // vert_def - "uniform vec2 detailScale;\n" - "varying vec2 fragDetailScale;\n" - "\n", - // vert_prog - " fragDetailScale = detailScale;\n" - " if (isNormalMapped == 0)\n" - " gl_TexCoord[1] = vec4(detailScale, 1.0, 1.0) * gl_MultiTexCoord0;\n" - "\n", - // frag_def - "uniform sampler2D detailMap;\n" - "varying vec2 fragDetailScale;\n" - "\n", - // frag_prog - " if (isNormalMapped == 0)\n" - " diffuseTexel *= texture2D(detailMap, gl_TexCoord[1].st);\n" - " else\n" - " diffuseTexel *= texture2D(detailMap, commonTexCoord.st * fragDetailScale);\n" - " diffuseTexel.rgb *= 2.0;\n" - "\n", - }, - { - 1 << PR_BIT_DIFFUSE_MODULATION, - // vert_def - "", - // vert_prog - " gl_FrontColor = gl_Color;\n" - "\n", - // frag_def - "", - // frag_prog - " if (isLightingPass == 0)\n" - " result *= vec4(gl_Color);\n" - "\n", - }, - { - 1 << PR_BIT_DIFFUSE_MAP2, - // vert_def - "", - // vert_prog - "", - // frag_def - "", - // frag_prog - " if (isLightingPass == 0)\n" - " result *= diffuseTexel;\n" - "\n", - }, - { - 1 << PR_BIT_HIGHPALOOKUP_MAP, - // vert_def - "", - // vert_prog - "", - // frag_def - "uniform sampler3D highPalookupMap;\n" - "\n", - // frag_prog - " float highPalScale = 0.9921875; // for 6 bits\n" - " float highPalBias = 0.00390625;\n" - "\n" - " if (isLightingPass == 0)\n" - " result.rgb = texture3D(highPalookupMap, result.rgb * highPalScale + highPalBias).rgb;\n" - " diffuseTexel.rgb = texture3D(highPalookupMap, diffuseTexel.rgb * highPalScale + highPalBias).rgb;\n" - "\n", - }, - { - 1 << PR_BIT_SPECULAR_MAP, - // vert_def - "", - // vert_prog - "", - // frag_def - "uniform sampler2D specMap;\n" - "\n", - // frag_prog - " specTexel = texture2D(specMap, commonTexCoord.st);\n" - "\n" - " isSpecularMapped = 1;\n" - "\n", - }, - { - 1 << PR_BIT_SPECULAR_MATERIAL, - // vert_def - "", - // vert_prog - "", - // frag_def - "uniform vec2 specMaterial;\n" - "\n", - // frag_prog - " specularMaterial = specMaterial;\n" - "\n", - }, - { - 1 << PR_BIT_MIRROR_MAP, - // vert_def - "", - // vert_prog - "", - // frag_def - "uniform sampler2DRect mirrorMap;\n" - "\n", - // frag_prog - " vec4 mirrorTexel;\n" - " vec2 mirrorCoords;\n" - "\n" - " mirrorCoords = gl_FragCoord.st;\n" - " if (isNormalMapped == 1) {\n" - " mirrorCoords += 100.0 * (normalTexel.rg - 0.5);\n" - " }\n" - " mirrorTexel = texture2DRect(mirrorMap, mirrorCoords);\n" - " result = vec4((result.rgb * (1.0 - specTexel.a)) + (mirrorTexel.rgb * specTexel.rgb * specTexel.a), result.a);\n" - "\n", - }, - { - 1 << PR_BIT_FOG, - // vert_def - "", - // vert_prog - "", - // frag_def -#ifdef PR_LINEAR_FOG - "uniform bool linearFog;\n" -#endif - "", - // frag_prog - " float fragDepth;\n" - " float fogFactor;\n" - "\n" - " fragDepth = gl_FragCoord.z / gl_FragCoord.w;\n" -#ifdef PR_LINEAR_FOG - " if (!linearFog) {\n" -#endif - " fragDepth *= fragDepth;\n" - " fogFactor = exp2(-gl_Fog.density * gl_Fog.density * fragDepth * 1.442695);\n" -#ifdef PR_LINEAR_FOG - " } else {\n" - " fogFactor = gl_Fog.scale * (gl_Fog.end - fragDepth);\n" - " fogFactor = clamp(fogFactor, 0.0, 1.0);" - " }\n" -#endif - " result.rgb = mix(gl_Fog.color.rgb, result.rgb, fogFactor);\n" - "\n", - }, - { - 1 << PR_BIT_GLOW_MAP, - // vert_def - "", - // vert_prog - "", - // frag_def - "uniform sampler2D glowMap;\n" - "\n", - // frag_prog - " vec4 glowTexel;\n" - "\n" - " glowTexel = texture2D(glowMap, commonTexCoord.st);\n" - " result = vec4((result.rgb * (1.0 - glowTexel.a)) + (glowTexel.rgb * glowTexel.a), result.a);\n" - "\n", - }, - { - 1 << PR_BIT_PROJECTION_MAP, - // vert_def - "uniform mat4 shadowProjMatrix;\n" - "\n", - // vert_prog - " gl_TexCoord[2] = shadowProjMatrix * curVertex;\n" - "\n", - // frag_def - "", - // frag_prog - "", - }, - { - 1 << PR_BIT_SHADOW_MAP, - // vert_def - "", - // vert_prog - "", - // frag_def - "uniform sampler2DShadow shadowMap;\n" - "\n", - // frag_prog - " shadowResult = shadow2DProj(shadowMap, gl_TexCoord[2]).a;\n" - "\n", - }, - { - 1 << PR_BIT_LIGHT_MAP, - // vert_def - "", - // vert_prog - "", - // frag_def - "uniform sampler2D lightMap;\n" - "\n", - // frag_prog - " lightTexel = texture2D(lightMap, vec2(gl_TexCoord[2].s, -gl_TexCoord[2].t) / gl_TexCoord[2].q).rgb;\n" - "\n", - }, - { - 1 << PR_BIT_SPOT_LIGHT, - // vert_def - "", - // vert_prog - "", - // frag_def - "uniform vec3 spotDir;\n" - "uniform vec2 spotRadius;\n" - "\n", - // frag_prog - " spotVector = spotDir;\n" - " spotCosRadius = spotRadius;\n" - " isSpotLight = 1;\n" - "\n", - }, - { - 1 << PR_BIT_POINT_LIGHT, - // vert_def - "varying vec3 vertexNormal;\n" - "varying vec3 eyeVector;\n" - "varying vec3 lightVector;\n" - "varying vec3 tangentSpaceLightVector;\n" - "\n", - // vert_prog - " vec3 vertexPos;\n" - "\n" - " vertexPos = vec3(gl_ModelViewMatrix * curVertex);\n" - " eyeVector = -vertexPos;\n" - " lightVector = gl_LightSource[0].ambient.rgb - vertexPos;\n" - "\n" - " if (isNormalMapped == 1) {\n" - " tangentSpaceLightVector = gl_LightSource[0].specular.rgb - vec3(curVertex);\n" - " tangentSpaceLightVector = TBN * tangentSpaceLightVector;\n" - " } else\n" - " vertexNormal = normalize(gl_NormalMatrix * curNormal);\n" - "\n", - // frag_def - "varying vec3 vertexNormal;\n" - "varying vec3 eyeVector;\n" - "varying vec3 lightVector;\n" - "varying vec3 tangentSpaceLightVector;\n" - "\n", - // frag_prog - " float pointLightDistance;\n" - " float lightAttenuation;\n" - " float spotAttenuation;\n" - " vec3 N, L, E, R, D;\n" - " vec3 lightDiffuse;\n" - " float lightSpecular;\n" - " float NdotL;\n" - " float spotCosAngle;\n" - "\n" - " L = normalize(lightVector);\n" - "\n" - " pointLightDistance = dot(lightVector,lightVector);\n" - " lightAttenuation = clamp(1.0 - pointLightDistance * gl_LightSource[0].linearAttenuation, 0.0, 1.0);\n" - " spotAttenuation = 1.0;\n" - "\n" - " if (isSpotLight == 1) {\n" - " D = normalize(spotVector);\n" - " spotCosAngle = dot(-L, D);\n" - " spotAttenuation = clamp((spotCosAngle - spotCosRadius.x) * spotCosRadius.y, 0.0, 1.0);\n" - " }\n" - "\n" - " if (isNormalMapped == 1) {\n" - " E = eyeVec;\n" - " N = normalize(2.0 * (normalTexel.rgb - 0.5));\n" - " L = normalize(tangentSpaceLightVector);\n" - " } else {\n" - " E = normalize(eyeVector);\n" - " N = normalize(vertexNormal);\n" - " }\n" - " NdotL = max(dot(N, L), 0.0);\n" - "\n" - " R = reflect(-L, N);\n" - "\n" - " lightDiffuse = gl_Color.a * shadowResult * lightTexel *\n" - " gl_LightSource[0].diffuse.rgb * lightAttenuation * spotAttenuation;\n" - " result += vec4(lightDiffuse * diffuseTexel.a * diffuseTexel.rgb * NdotL, 0.0);\n" - "\n" - " if (isSpecularMapped == 0)\n" - " specTexel.rgb = diffuseTexel.rgb * diffuseTexel.a;\n" - "\n" - " lightSpecular = pow( max(dot(R, E), 0.0), specularMaterial.x * specTexel.a) * specularMaterial.y;\n" - " result += vec4(lightDiffuse * specTexel.rgb * lightSpecular, 0.0);\n" - "\n", - }, - { - 1 << PR_BIT_FOOTER, - // vert_def - "void main(void)\n" - "{\n" - " vec4 curVertex = gl_Vertex;\n" - " vec3 curNormal = gl_Normal;\n" - " int isNormalMapped = 0;\n" - " mat3 TBN;\n" - "\n" - " gl_TexCoord[0] = gl_MultiTexCoord0;\n" - "\n", - // vert_prog - " gl_Position = gl_ModelViewProjectionMatrix * curVertex;\n" - "}\n", - // frag_def - "void main(void)\n" - "{\n" - " vec3 commonTexCoord = vec3(gl_TexCoord[0].st, 0.0);\n" - " vec4 result = vec4(1.0, 1.0, 1.0, 1.0);\n" - " vec4 diffuseTexel = vec4(1.0, 1.0, 1.0, 1.0);\n" - " vec4 specTexel = vec4(1.0, 1.0, 1.0, 1.0);\n" - " vec4 normalTexel;\n" - " int isLightingPass = 0;\n" - " int isNormalMapped = 0;\n" - " int isSpecularMapped = 0;\n" - " vec3 eyeVec;\n" - " int isSpotLight = 0;\n" - " vec3 spotVector;\n" - " vec2 spotCosRadius;\n" - " float shadowResult = 1.0;\n" - " vec2 specularMaterial = vec2(15.0, 1.0);\n" - " vec3 lightTexel = vec3(1.0, 1.0, 1.0);\n" - "\n", - // frag_prog - " gl_FragColor = result;\n" - "}\n", - } -}; - -_prprograminfo prprograms[1 << PR_BIT_COUNT]; - -int32_t overridematerial; -int32_t globaloldoverridematerial; - -int32_t rotatespritematerialbits; - -// RENDER TARGETS -_prrt *prrts; - -// CONTROL -GLfloat spritemodelview[16]; -GLfloat mdspritespace[4][4]; -GLfloat rootmodelviewmatrix[16]; -GLfloat *curmodelviewmatrix; -GLfloat rootskymodelviewmatrix[16]; -GLfloat *curskymodelviewmatrix; - -static int16_t sectorqueue[MAXSECTORS]; -static int16_t querydelay[MAXSECTORS]; -static GLuint queryid[MAXWALLS]; -static int16_t drawingstate[MAXSECTORS]; - -int16_t *cursectormasks; -int16_t *cursectormaskcount; - -float horizang; -fix16_t viewangle; - -int32_t depth; -_prmirror mirrors[10]; - -#if defined __clang__ && defined __APPLE__ -// XXX: OS X 10.9 deprecated GLUtesselator. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif -GLUtesselator* prtess; -#if defined __clang__ && defined __APPLE__ -#pragma clang diagnostic pop -#endif - -static int16_t cursky; -static char curskypal; -static int8_t curskyshade; -static float curskyangmul = 1; - -_pranimatespritesinfo asi; - -int32_t polymersearching; - -int32_t culledface; - -// EXTERNAL FUNCTIONS -int32_t polymer_init(void) -{ - int32_t i, j, t = timerGetTicks(); - - if (pr_verbosity >= 1) OSD_Printf("Initializing Polymer subsystem...\n"); - - if (!glinfo.texnpot || - !glinfo.depthtex || - !glinfo.shadow || - !glinfo.fbos || - !glinfo.rect || - !glinfo.multitex || - !glinfo.vbos || - !glinfo.occlusionqueries || - !glinfo.glsl) - { - OSD_Printf("PR : Your video card driver/combo doesn't support the necessary features!\n"); - OSD_Printf("PR : Disabling Polymer...\n"); - return 0; - } - - // clean up existing stuff since it will be initialized again if we're re-entering here - polymer_uninit(); - - Bmemset(&prsectors[0], 0, sizeof(prsectors[0]) * MAXSECTORS); - Bmemset(&prwalls[0], 0, sizeof(prwalls[0]) * MAXWALLS); - - prtess = bgluNewTess(); - if (prtess == 0) - { - OSD_Printf("PR : Tessellation object initialization failed!\n"); - return 0; - } - - polymer_loadboard(); - - polymer_initartsky(); - skyboxdatavbo = 0; - - i = 0; - while (i < nextmodelid) - { - if (models[i]) - { - md3model_t* m; - - m = (md3model_t*)models[i]; - m->indices = NULL; - } - i++; - } - - i = 0; - while (i < (1 << PR_BIT_COUNT)) - { - prprograms[i].handle = 0; - i++; - } - - overridematerial = 0xFFFFFFFF; - - polymersearching = FALSE; - - polymer_initrendertargets(pr_shadowcount + 1); - - // Prime highpalookup maps - i = 0; - while (i < MAXBASEPALS) - { - j = 0; - while (j < MAXPALOOKUPS) - { - if (prhighpalookups[i][j].data) - { - glGenTextures(1, &prhighpalookups[i][j].map); - glBindTexture(GL_TEXTURE_3D, prhighpalookups[i][j].map); - glTexImage3D(GL_TEXTURE_3D, // target - 0, // mip level - GL_RGBA, // internalFormat - PR_HIGHPALOOKUP_DIM, // width - PR_HIGHPALOOKUP_DIM, // height - PR_HIGHPALOOKUP_DIM, // depth - 0, // border - GL_BGRA, // upload format - GL_UNSIGNED_BYTE, // upload component type - prhighpalookups[i][j].data); // data pointer - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); - glBindTexture(GL_TEXTURE_3D, 0); - } - j++; - } - i++; - } - -#ifndef __APPLE__ - if (glinfo.debugoutput) { - // Enable everything. - glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); - glDebugMessageCallbackARB((GLDEBUGPROCARB)polymer_debugoutputcallback, NULL); - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); - } -#endif - - if (pr_verbosity >= 1) OSD_Printf("PR : Initialization complete in %d ms.\n", timerGetTicks()-t); - - return 1; -} - -void polymer_uninit(void) -{ - int32_t i, j; - - if (prtess) - { - bgluDeleteTess(prtess); - prtess = NULL; - } - - polymer_freeboard(); - - polymer_initrendertargets(0); - - i = 0; - while (i < MAXBASEPALS) - { - j = 0; - while (j < MAXPALOOKUPS) - { -// if (prhighpalookups[i][j].data) { -// DO_FREE_AND_NULL(prhighpalookups[i][j].data); -// } - if (prhighpalookups[i][j].map) { - glDeleteTextures(1, &prhighpalookups[i][j].map); - prhighpalookups[i][j].map = 0; - } - j++; - } - i++; - } - - i = 0; - while (plpool) - { - _prplanelist* next = plpool->n; - - Bfree(plpool); - plpool = next; - i++; - } - - if (pr_verbosity >= 3) - OSD_Printf("PR: freed %d planelists\n", i); -} - -void polymer_setaspect(int32_t ang) -{ - float aspect; - float fang = (float)ang * atanf(fviewingrange*(1.f/65536.f)) * (4.f/fPI); - - // use horizontal fov instead of vertical - fang = atanf(tanf(fang * (fPI / 2048.f)) * float(windowxy2.y - windowxy1.y + 1) / float(windowxy2.x - windowxy1.x + 1) * - float(xdim) / float(ydim) * (3.f / 4.f)) * (2048.f / fPI); - - if (pr_customaspect != 0.0f) - aspect = pr_customaspect; - else - aspect = (float)(windowxy2.x-windowxy1.x+1) / - (float)(windowxy2.y-windowxy1.y+1); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - bgluPerspective(fang * (360.f/2048.f), aspect, 0.01f, 100.0f); -} - -void polymer_glinit(void) -{ - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClearStencil(0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glViewport(windowxy1.x, ydim-(windowxy2.y+1),windowxy2.x-windowxy1.x+1, windowxy2.y-windowxy1.y+1); - - // texturing - glEnable(GL_TEXTURE_2D); - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - - glDisable(GL_BLEND); - glDisable(GL_ALPHA_TEST); - - if (pr_wireframe) - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - else - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - polymer_setaspect(pr_fov); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - glDisable(GL_FOG); - - culledface = GL_BACK; - glCullFace(GL_BACK); - glFrontFace(GL_CCW); - - glEnable(GL_CULL_FACE); -} - -void polymer_resetlights(void) -{ - int32_t i; - _prsector *s; - _prwall *w; - - i = 0; - while (i < numsectors) - { - s = prsectors[i]; - - if (!s) { - i++; - continue; - } - - polymer_resetplanelights(&s->floor); - polymer_resetplanelights(&s->ceil); - - i++; - } - - i = 0; - while (i < numwalls) - { - w = prwalls[i]; - - if (!w) { - i++; - continue; - } - - polymer_resetplanelights(&w->wall); - polymer_resetplanelights(&w->over); - polymer_resetplanelights(&w->mask); - - i++; - } - - i = 0; - while (i < PR_MAXLIGHTS) - { - prlights[i].flags.active = 0; - i++; - } - - lightcount = 0; - - if (!engineLoadMHK(NULL)) - OSD_Printf("polymer_resetlights: reloaded maphack\n"); -} - -void polymer_loadboard(void) -{ - int32_t i; - - polymer_freeboard(); - - // in the big map buffer, sectors have floor and ceiling vertices for each wall first, then walls - prwalldataoffset = numwalls * 2 * sizeof(_prvert); - - glGenBuffers(1, &prmapvbo); - glBindBuffer(GL_ARRAY_BUFFER, prmapvbo); - glBufferData(GL_ARRAY_BUFFER, prwalldataoffset + (numwalls * prwalldatasize), NULL, mapvbousage); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glGenBuffers(1, &prindexringvbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prindexringvbo); - - if (pr_buckets) - { - glBufferStorage(GL_ELEMENT_ARRAY_BUFFER, prindexringsize * sizeof(GLuint), NULL, prindexringmapflags | GL_DYNAMIC_STORAGE_BIT); - prindexring = (GLuint*)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, prindexringsize * sizeof(GLuint), prindexringmapflags); - } - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - i = 0; - while (i < numsectors) - { - polymer_initsector(i); - polymer_updatesector(i); - i++; - } - - i = 0; - while (i < numwalls) - { - polymer_initwall(i); - polymer_updatewall(i); - i++; - } - - polymer_getsky(); - - polymer_resetlights(); - - if (pr_verbosity >= 1 && numsectors) OSD_Printf("PR : Board loaded.\n"); -} - -// The parallaxed ART sky angle divisor corresponding to a horizfrac of 32768. -#define DEFAULT_ARTSKY_ANGDIV 4.3027f - -void polymer_drawrooms(int32_t daposx, int32_t daposy, int32_t daposz, fix16_t daang, fix16_t dahoriz, int16_t dacursectnum) -{ - int16_t cursectnum; - int32_t i, cursectflorz, cursectceilz; - float skyhoriz, ang, tiltang; - float pos[3]; - pthtyp* pth; - - if (videoGetRenderMode() == REND_CLASSIC) return; - - videoBeginDrawing(); - - // TODO: support for screen resizing - // frameoffset = frameplace + windowxy1.y*bytesperline + windowxy1.x; - - if (pr_verbosity >= 3) OSD_Printf("PR : Drawing rooms...\n"); - - // fogcalc_old needs this - gvisibility = ((float)globalvisibility)*FOGSCALE; - - ang = fix16_to_float(daang) * (360.f/2048.f); - horizang = -(float)atan2f(fix16_to_float(dahoriz) - 100.f, 128.f) * (180.f * (float)M_1_PI); - tiltang = (gtang * 90.0f); - - pos[0] = (float)daposy; - pos[1] = -(float)(daposz) / 16.0f; - pos[2] = -(float)daposx; - - polymer_updatelights(); - -// polymer_resetlights(); -// if (pr_lighting) -// polymer_applylights(); - - depth = 0; - - if (pr_shadows && lightcount && (pr_shadowcount > 0)) - polymer_prepareshadows(); - - // hack for parallax skies - skyhoriz = horizang; - if (skyhoriz < -180.0f) - skyhoriz += 360.0f; - - drawingskybox = 1; - pth = texcache_fetch(cursky, 0, 0, DAMETH_NOMASK); - drawingskybox = 0; - - // if it's not a skybox, make the sky parallax - // DEFAULT_ARTSKY_ANGDIV is computed from eyeballed values - // need to recompute it if we ever change the max horiz amplitude - if (!pth || !(pth->flags & PTH_SKYBOX)) - skyhoriz *= curskyangmul; - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glRotatef(tiltang, 0.0f, 0.0f, -1.0f); - glRotatef(skyhoriz, 1.0f, 0.0f, 0.0f); - glRotatef(ang, 0.0f, 1.0f, 0.0f); - - glScalef(1.0f / 1000.0f, 1.0f / 1000.0f, 1.0f / 1000.0f); - glTranslatef(-pos[0], -pos[1], -pos[2]); - - glGetFloatv(GL_MODELVIEW_MATRIX, rootskymodelviewmatrix); - - curskymodelviewmatrix = rootskymodelviewmatrix; - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glRotatef(tiltang, 0.0f, 0.0f, -1.0f); - glRotatef(horizang, 1.0f, 0.0f, 0.0f); - glRotatef(ang, 0.0f, 1.0f, 0.0f); - - glScalef(1.0f / 1000.0f, 1.0f / 1000.0f, 1.0f / 1000.0f); - glTranslatef(-pos[0], -pos[1], -pos[2]); - - glGetFloatv(GL_MODELVIEW_MATRIX, rootmodelviewmatrix); - - cursectnum = dacursectnum; - updatesectorbreadth(daposx, daposy, &cursectnum); - - if (cursectnum >= 0 && cursectnum < numsectors) - dacursectnum = cursectnum; - else if (pr_verbosity>=2) - OSD_Printf("PR : got sector %d after update!\n", cursectnum); - - // unflag all sectors - i = numsectors-1; - while (i >= 0) - { - prsectors[i]->flags.uptodate = 0; - prsectors[i]->wallsproffset = 0.0f; - prsectors[i]->floorsproffset = 0.0f; - i--; - } - i = numwalls-1; - while (i >= 0) - { - prwalls[i]->flags.uptodate = 0; - i--; - } - - if (searchit == 2 && !polymersearching) - { - globaloldoverridematerial = overridematerial; - overridematerial = prprogrambits[PR_BIT_DIFFUSE_MODULATION].bit; - overridematerial |= prprogrambits[PR_BIT_DIFFUSE_MAP2].bit; - polymersearching = TRUE; - } - if (!searchit && polymersearching) { - overridematerial = globaloldoverridematerial; - polymersearching = FALSE; - } - - if (dacursectnum > -1 && dacursectnum < numsectors) - getzsofslope(dacursectnum, daposx, daposy, &cursectceilz, &cursectflorz); - - // external view (editor) - if ((dacursectnum < 0) || (dacursectnum >= numsectors) || - (daposz > cursectflorz) || - (daposz < cursectceilz)) - { - prcanbucket = 1; - - if (!editstatus && pr_verbosity>=1) - { - if ((unsigned)dacursectnum < (unsigned)numsectors) - OSD_Printf("PR : EXT sec=%d z=%d (%d, %d)\n", dacursectnum, daposz, cursectflorz, cursectceilz); - else - OSD_Printf("PR : EXT sec=%d z=%d\n", dacursectnum, daposz); - } - - curmodelviewmatrix = rootmodelviewmatrix; - i = numsectors-1; - while (i >= 0) - { - polymer_updatesector(i); - polymer_drawsector(i, FALSE); - polymer_scansprites(i, tsprite, &spritesortcnt); - i--; - } - - i = numwalls-1; - while (i >= 0) - { - polymer_updatewall(i); - polymer_drawwall(sectorofwall(i), i); - i--; - } - - polymer_emptybuckets(); - - viewangle = daang; - videoEndDrawing(); - return; - } - - // GO! - polymer_displayrooms(dacursectnum); - - curmodelviewmatrix = rootmodelviewmatrix; - - // build globals used by rotatesprite - viewangle = daang; - set_globalang(daang); - - // polymost globals used by polymost_dorotatesprite - gcosang = fcosglobalang*(1./262144.f); - gsinang = fsinglobalang*(1./262144.f); - gcosang2 = gcosang*fviewingrange*(1./65536.f); - gsinang2 = gsinang*fviewingrange*(1./65536.f); - - if (pr_verbosity >= 3) OSD_Printf("PR : Rooms drawn.\n"); - videoEndDrawing(); -} - -void polymer_drawmasks(void) -{ - glEnable(GL_ALPHA_TEST); - glEnable(GL_BLEND); -// glEnable(GL_POLYGON_OFFSET_FILL); - -// while (--spritesortcnt) -// { -// tspriteptr[spritesortcnt] = &tsprite[spritesortcnt]; -// polymer_drawsprite(spritesortcnt); -// } - - glEnable(GL_CULL_FACE); - - if (cursectormaskcount) { - // We (kind of) queue sector masks near to far, so drawing them in reverse - // order is the sane approach here. Of course impossible cases will arise. - while (*cursectormaskcount) { - polymer_drawsector(cursectormasks[--(*cursectormaskcount)], TRUE); - } - - // This should _always_ be called after a corresponding pr_displayrooms() - // unless we're in "external view" mode, which was checked above. - // Both the top-level game drawrooms and the recursive internal passes - // should be accounted for here. If these free cause corruption, there's - // an accounting bug somewhere. - DO_FREE_AND_NULL(cursectormaskcount); - DO_FREE_AND_NULL(cursectormasks); - } - - glDisable(GL_CULL_FACE); - -// glDisable(GL_POLYGON_OFFSET_FILL); - glDisable(GL_BLEND); - glDisable(GL_ALPHA_TEST); -} - -void polymer_editorpick(void) -{ - GLubyte picked[3]; - int16_t num; - - glReadPixels(searchx, ydim - searchy, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, picked); - - num = B_UNBUF16(&picked[1]); - - searchstat = picked[0]; - - switch (searchstat) { - case 0: // wall - case 5: // botomwall - case 4: // 1-way/masked wall - searchsector = sectorofwall(num); - searchbottomwall = searchwall = num; - searchisbottom = (searchstat==5); - if (searchstat == 5) { - searchstat = 0; - if (wall[num].nextwall >= 0 && (wall[num].cstat & 2)) { - searchbottomwall = wall[num].nextwall; - } - } - break; - case 1: // floor - case 2: // ceiling - searchsector = num; - - // Apologies to Plagman for littering here, but this feature is quite essential - { - GLdouble model[16]; - GLdouble proj[16]; - GLint view[4]; - - GLdouble x,y,z; - GLfloat scr[3], scrv[3]; - GLdouble scrx,scry,scrz; - GLfloat dadepth; - - int16_t k, bestk=0; - GLfloat bestwdistsq = (GLfloat)3.4e38, wdistsq; - GLfloat w1[2], w2[2], w21[2], pw1[2], pw2[2]; - GLfloat ptonline[2]; - GLfloat scrvxz[2]; - GLfloat scrvxznorm, scrvxzn[2], scrpxz[2]; - GLfloat w1d, w2d; - walltype *wal = &wall[sector[searchsector].wallptr]; - - GLfloat t, svcoeff, p[2]; - GLfloat *pl; - - glGetDoublev(GL_MODELVIEW_MATRIX, model); - glGetDoublev(GL_PROJECTION_MATRIX, proj); - glGetIntegerv(GL_VIEWPORT, view); - - glReadPixels(searchx, ydim-searchy, 1,1, GL_DEPTH_COMPONENT, GL_FLOAT, &dadepth); - bgluUnProject(searchx, ydim-searchy, dadepth, model, proj, view, &x, &y, &z); - bgluUnProject(searchx, ydim-searchy, 0.0, model, proj, view, &scrx, &scry, &scrz); - - scr[0]=scrx, scr[1]=scry, scr[2]=scrz; - - scrv[0] = x-scrx; - scrv[1] = y-scry; - scrv[2] = z-scrz; - - scrvxz[0] = x-scrx; - scrvxz[1] = z-scrz; - - if (prsectors[searchsector]==NULL) - { - //OSD_Printf("polymer_editorpick: prsectors[searchsector]==NULL !!!\n"); - searchwall = sector[num].wallptr; - } - else - { - if (searchstat==1) - pl = prsectors[searchsector]->ceil.plane; - else - pl = prsectors[searchsector]->floor.plane; - - if (pl == NULL) - { - searchwall = sector[num].wallptr; - return; - } - - t = dot3f(pl,scrv); - svcoeff = -(dot3f(pl,scr)+pl[3])/t; - - // point on plane (x and z) - p[0] = scrx + svcoeff*scrv[0]; - p[1] = scrz + svcoeff*scrv[2]; - - for (k=0; kmaterial.diffusemodulation[0] = modulation; - plane->material.diffusemodulation[1] = ((GLubyte const *) data)[0]; - plane->material.diffusemodulation[2] = ((GLubyte const *) data)[1]; - plane->material.diffusemodulation[3] = 0xFF; -} - -static void polymer_drawsearchplane(_prplane *plane, GLubyte *oldcolor, GLubyte modulation, GLubyte *data) -{ - Bmemcpy(oldcolor, plane->material.diffusemodulation, sizeof(GLubyte) * 4); - - polymer_setupdiffusemodulation(plane, modulation, data); - - polymer_drawplane(plane); - - Bmemcpy(plane->material.diffusemodulation, oldcolor, sizeof(GLubyte) * 4); -} - -void polymer_drawmaskwall(int32_t damaskwallcnt) -{ - usectortype *sec; - walltype *wal; - _prwall *w; - GLubyte oldcolor[4]; - - if (pr_verbosity >= 3) OSD_Printf("PR : Masked wall %i...\n", damaskwallcnt); - - sec = (usectortype *)§or[sectorofwall(maskwall[damaskwallcnt])]; - wal = &wall[maskwall[damaskwallcnt]]; - w = prwalls[maskwall[damaskwallcnt]]; - - glEnable(GL_CULL_FACE); - - if (searchit == 2) { - polymer_drawsearchplane(&w->mask, oldcolor, 0x04, (GLubyte *)&maskwall[damaskwallcnt]); - } else { - calc_and_apply_fog(wal->picnum, fogshade(wal->shade, wal->pal), sec->visibility, get_floor_fogpal(sec)); - polymer_drawplane(&w->mask); - } - - glDisable(GL_CULL_FACE); -} - -void polymer_drawsprite(int32_t snum) -{ - int32_t i, j, cs; - _prsprite *s; - - uspritetype *const tspr = tspriteptr[snum]; - const usectortype *sec; - - if (pr_verbosity >= 3) OSD_Printf("PR : Sprite %i...\n", snum); - - if (bad_tspr(tspr)) - return; - - if ((tspr->cstat & 8192) && (depth && !mirrors[depth-1].plane)) - return; - - if ((tspr->cstat & 16384) && (!depth || mirrors[depth-1].plane)) - return; - - DO_TILE_ANIM(tspr->picnum, tspr->owner+32768); - - sec = (usectortype *)§or[tspr->sectnum]; - calc_and_apply_fog(tspr->picnum, fogshade(tspr->shade, tspr->pal), sec->visibility, - get_floor_fogpal((usectortype *)§or[tspr->sectnum])); - - if (usemodels && tile2model[Ptile2tile(tspr->picnum,tspr->pal)].modelid >= 0 && - tile2model[Ptile2tile(tspr->picnum,tspr->pal)].framenum >= 0 && - !(spriteext[tspr->owner].flags & SPREXT_NOTMD)) - { - glEnable(GL_CULL_FACE); - SWITCH_CULL_DIRECTION; - polymer_drawmdsprite(tspr); - SWITCH_CULL_DIRECTION; - glDisable(GL_CULL_FACE); - return; - } - - cs = tspr->cstat; - - // I think messing with the tspr is safe at this point? - // If not, change that to modify a temp position in updatesprite itself. - // I don't think this flags are meant to change on the fly so it'd possibly - // be safe to cache a plane that has them applied. - if (spriteext[tspr->owner].flags & SPREXT_AWAY1) - { - tspr->x += sintable[(tspr->ang + 512) & 2047] >> 13; - tspr->y += sintable[tspr->ang & 2047] >> 13; - } - else if (spriteext[tspr->owner].flags & SPREXT_AWAY2) - { - tspr->x -= sintable[(tspr->ang + 512) & 2047] >> 13; - tspr->y -= sintable[tspr->ang & 2047] >> 13; - } - - polymer_updatesprite(snum); - - Bassert(tspr->owner < MAXSPRITES); - s = prsprites[tspr->owner]; - - if (s == NULL) - return; - - switch ((tspr->cstat>>4) & 3) - { - case 1: - prsectors[tspr->sectnum]->wallsproffset += 0.5f; - if (!depth || mirrors[depth-1].plane) - glPolygonOffset(-1.0f, -1.0f); - break; - case 2: - prsectors[tspr->sectnum]->floorsproffset += 0.5f; - if (!depth || mirrors[depth-1].plane) - glPolygonOffset(-1.0f, -1.0f); - break; - } - - if ((cs & 48) == 0) - { - int32_t curpriority = 0; - - s->plane.lightcount = 0; - - while ((curpriority < pr_maxlightpriority) && (!depth || mirrors[depth-1].plane)) - { - i = j = 0; - while (j < lightcount) - { - while (!prlights[i].flags.active) - i++; - - if (prlights[i].priority != curpriority) - { - i++; - j++; - continue; - } - - if (polymer_planeinlight(&s->plane, &prlights[i])) - s->plane.lights[s->plane.lightcount++] = i; - - i++; - j++; - } - curpriority++; - } - } - - if ((tspr->cstat & 64) && (tspr->cstat & SPR_ALIGN_MASK)) - { - if ((tspr->cstat & SPR_ALIGN_MASK)==SPR_FLOOR && (tspr->cstat & SPR_YFLIP)) - SWITCH_CULL_DIRECTION; - glEnable(GL_CULL_FACE); - } - - if ((!depth || mirrors[depth-1].plane) && !pr_ati_nodepthoffset) - glEnable(GL_POLYGON_OFFSET_FILL); - - polymer_drawplane(&s->plane); - - if ((!depth || mirrors[depth-1].plane) && !pr_ati_nodepthoffset) - glDisable(GL_POLYGON_OFFSET_FILL); - - if ((tspr->cstat & 64) && (tspr->cstat & SPR_ALIGN_MASK)) - { - if ((tspr->cstat & SPR_ALIGN_MASK)==SPR_FLOOR && (tspr->cstat & SPR_YFLIP)) - SWITCH_CULL_DIRECTION; - glDisable(GL_CULL_FACE); - } -} - -void polymer_setanimatesprites(animatespritesptr animatesprites, int32_t x, int32_t y, int32_t a, int32_t smoothratio) -{ - asi.animatesprites = animatesprites; - asi.x = x; - asi.y = y; - asi.a = a; - asi.smoothratio = smoothratio; -} - -int16_t polymer_addlight(_prlight* light) -{ - int32_t lighti; - - if (lightcount >= PR_MAXLIGHTS || light->priority > pr_maxlightpriority || !pr_lighting) - return -1; - - if ((light->sector == -1) || (light->sector >= numsectors)) - return -1; - - lighti = 0; - while ((lighti < PR_MAXLIGHTS) && (prlights[lighti].flags.active)) - lighti++; - - if (lighti == PR_MAXLIGHTS) - return -1; -#if 0 - // Spot lights disabled on ATI cards because they cause crashes with - // Catalyst 12.8 drivers. - // See: http://forums.duke4.net/topic/5723-hrp-polymer-crash/ - if (pr_ati_fboworkaround && light->radius) - return -1; -#endif - Bmemcpy(&prlights[lighti], light, sizeof(_prlight)); - - if (light->radius) { - polymer_processspotlight(&prlights[lighti]); - - // get the texture handle for the lightmap - if (light->tilenum > 0) { - int16_t picnum = light->tilenum; - pthtyp* pth; - - DO_TILE_ANIM(picnum, 0); - - if (!waloff[picnum]) - tileLoad(picnum); - - pth = NULL; - pth = texcache_fetch(picnum, 0, 0, DAMETH_NOMASK); - - if (pth) - light->lightmap = pth->glpic; - } - } - - prlights[lighti].flags.isinview = 0; - prlights[lighti].flags.active = 1; - - prlights[lighti].flags.invalidate = 0; - - prlights[lighti].planecount = 0; - prlights[lighti].planelist = NULL; - - polymer_culllight(lighti); - - lightcount++; - - return lighti; -} - -void polymer_deletelight(int16_t lighti) -{ - if (!prlights[lighti].flags.active) - { -#ifdef DEBUGGINGAIDS - if (pr_verbosity >= 2) - OSD_Printf("PR : Called polymer_deletelight on inactive light\n"); - // currently known cases: when reloading maphack lights (didn't set maphacklightcnt=0 - // but did loadmaphack()->delete_maphack_lights() after polymer_resetlights()) -#endif - return; - } - - polymer_removelight(lighti); - - prlights[lighti].flags.active = 0; - - lightcount--; -} - -void polymer_invalidatelights(void) -{ - int32_t i = PR_MAXLIGHTS-1; - - do - prlights[i].flags.invalidate = prlights[i].flags.active; - while (i--); -} - -void polymer_texinvalidate(void) -{ - int32_t i; - - i = 0; - - while (i < MAXSPRITES) { - polymer_invalidatesprite(i); - i++; - } - - i = numsectors - 1; - - if (!numsectors || !prsectors[i]) - return; - - do - prsectors[i--]->flags.invalidtex = 1; - while (i >= 0); - - i = numwalls - 1; - do - prwalls[i--]->flags.invalidtex = 1; - while (i >= 0); -} - -void polymer_definehighpalookup(char basepalnum, char palnum, char *data) -{ - prhighpalookups[basepalnum][palnum].data = (char *)Xmalloc(PR_HIGHPALOOKUP_DATA_SIZE); - - Bmemcpy(prhighpalookups[basepalnum][palnum].data, data, PR_HIGHPALOOKUP_DATA_SIZE); -} - -int32_t polymer_havehighpalookup(int32_t basepalnum, int32_t palnum) -{ - if ((uint32_t)basepalnum >= MAXBASEPALS || (uint32_t)palnum >= MAXPALOOKUPS) - return 0; - - return (prhighpalookups[basepalnum][palnum].data != NULL); -} - - -// CORE -static void polymer_displayrooms(const int16_t dacursectnum) -{ - usectortype *sec; - int32_t i; - int16_t bunchnum; - int16_t ns; - GLint result; - int16_t doquery; - int32_t front; - int32_t back; - GLfloat localskymodelviewmatrix[16]; - GLfloat localmodelviewmatrix[16]; - GLfloat localprojectionmatrix[16]; - float frustum[5 * 4]; - int32_t localspritesortcnt; - uspritetype localtsprite[MAXSPRITESONSCREEN]; - int16_t localmaskwall[MAXWALLSB]; - int16_t localmaskwallcnt; - _prmirror mirrorlist[10]; - int mirrorcount; - int16_t *localsectormasks; - int16_t *localsectormaskcount; - int32_t gx, gy, gz, px, py, pz; - GLdouble plane[4]; - float coeff; - - curmodelviewmatrix = localmodelviewmatrix; - glGetFloatv(GL_MODELVIEW_MATRIX, localmodelviewmatrix); - glGetFloatv(GL_PROJECTION_MATRIX, localprojectionmatrix); - - polymer_extractfrustum(localmodelviewmatrix, localprojectionmatrix, frustum); - - Bmemset(querydelay, 0, sizeof(int16_t) * numsectors); - Bmemset(queryid, 0, sizeof(GLuint) * numwalls); - Bmemset(drawingstate, 0, sizeof(int16_t) * numsectors); - - front = 0; - back = 1; - sectorqueue[0] = dacursectnum; - drawingstate[dacursectnum] = 1; - - localspritesortcnt = localmaskwallcnt = 0; - - mirrorcount = 0; - - localsectormasks = (int16_t *)Xmalloc(sizeof(int16_t) * numsectors); - localsectormaskcount = (int16_t *)Xcalloc(sizeof(int16_t), 1); - cursectormasks = localsectormasks; - cursectormaskcount = localsectormaskcount; - - glDisable(GL_DEPTH_TEST); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - polymer_drawsky(cursky, curskypal, curskyshade); - glEnable(GL_DEPTH_TEST); - - // depth-only occlusion testing pass -// overridematerial = 0; - - prcanbucket = 1; - - while (front != back) - { - sec = (usectortype *)§or[sectorqueue[front]]; - - polymer_pokesector(sectorqueue[front]); - polymer_drawsector(sectorqueue[front], FALSE); - polymer_scansprites(sectorqueue[front], localtsprite, &localspritesortcnt); - - doquery = 0; - - i = sec->wallnum-1; - do - { - // if we have a level boundary somewhere in the sector, - // consider these walls as visportals - if (wall[sec->wallptr + i].nextsector < 0 && pr_buckets == 0) - doquery = 1; - } - while (--i >= 0); - - i = sec->wallnum-1; - while (i >= 0) - { - if ((wall[sec->wallptr + i].nextsector >= 0) && - (wallvisible(globalposx, globalposy, sec->wallptr + i)) && - (polymer_planeinfrustum(&prwalls[sec->wallptr + i]->mask, frustum))) - { - if ((prwalls[sec->wallptr + i]->mask.vertcount == 4) && - !(prwalls[sec->wallptr + i]->underover & 4) && - !(prwalls[sec->wallptr + i]->underover & 8)) - { - // early exit for closed sectors - _prwall *w; - - w = prwalls[sec->wallptr + i]; - - if ((w->mask.buffer[0].y >= w->mask.buffer[3].y) && - (w->mask.buffer[1].y >= w->mask.buffer[2].y)) - { - i--; - continue; - } - } - - if ((wall[sec->wallptr + i].cstat & 48) == 16) - { - int pic = wall[sec->wallptr + i].overpicnum; - - if (tilesiz[pic].x > 0 && tilesiz[pic].y > 0) - localmaskwall[localmaskwallcnt++] = sec->wallptr + i; - } - - if (!depth && (overridematerial & prprogrambits[PR_BIT_MIRROR_MAP].bit) && - wall[sec->wallptr + i].overpicnum == 560 && - wall[sec->wallptr + i].cstat & 32) - { - mirrorlist[mirrorcount].plane = &prwalls[sec->wallptr + i]->mask; - mirrorlist[mirrorcount].sectnum = sectorqueue[front]; - mirrorlist[mirrorcount].wallnum = sec->wallptr + i; - mirrorcount++; - } - - if (!(wall[sec->wallptr + i].cstat & 32)) { - if (doquery && (!drawingstate[wall[sec->wallptr + i].nextsector])) - { - float pos[3], sqdist; - int32_t oldoverridematerial; - - pos[0] = fglobalposy; - pos[1] = fglobalposz * (-1.f/16.f); - pos[2] = -fglobalposx; - - sqdist = prwalls[sec->wallptr + i]->mask.plane[0] * pos[0] + - prwalls[sec->wallptr + i]->mask.plane[1] * pos[1] + - prwalls[sec->wallptr + i]->mask.plane[2] * pos[2] + - prwalls[sec->wallptr + i]->mask.plane[3]; - - // hack to avoid occlusion querying portals that are too close to the viewpoint - // this is needed because of the near z-clipping plane; - if (sqdist < 100) - queryid[sec->wallptr + i] = 0xFFFFFFFF; - else { - _prwall *w; - - w = prwalls[sec->wallptr + i]; - - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - glDepthMask(GL_FALSE); - - glGenQueries(1, &queryid[sec->wallptr + i]); - glBeginQuery(GL_SAMPLES_PASSED, queryid[sec->wallptr + i]); - - oldoverridematerial = overridematerial; - overridematerial = 0; - - if ((w->underover & 4) && (w->underover & 1)) - polymer_drawplane(&w->wall); - polymer_drawplane(&w->mask); - if ((w->underover & 8) && (w->underover & 2)) - polymer_drawplane(&w->over); - - overridematerial = oldoverridematerial; - - glEndQuery(GL_SAMPLES_PASSED); - - glDepthMask(GL_TRUE); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } - } else - queryid[sec->wallptr + i] = 0xFFFFFFFF; - } - } - - i--; - } - - // Cram as much CPU or GPU work as we can between queuing the - // occlusion queries and reaping them. - i = sec->wallnum-1; - do - { - if (wallvisible(globalposx, globalposy, sec->wallptr + i)) - polymer_drawwall(sectorqueue[front], sec->wallptr + i); - } - while (--i >= 0); -#ifdef YAX_ENABLE - // queue ROR neighbors - if ((bunchnum = yax_getbunch(sectorqueue[front], YAX_FLOOR)) >= 0) { - - for (SECTORS_OF_BUNCH(bunchnum, YAX_CEILING, ns)) { - - if (ns >= 0 && !drawingstate[ns] && - polymer_planeinfrustum(&prsectors[ns]->ceil, frustum)) { - - sectorqueue[back++] = ns; - drawingstate[ns] = 1; - } - } - } - - if ((bunchnum = yax_getbunch(sectorqueue[front], YAX_CEILING)) >= 0) { - - for (SECTORS_OF_BUNCH(bunchnum, YAX_FLOOR, ns)) { - - if (ns >= 0 && !drawingstate[ns] && - polymer_planeinfrustum(&prsectors[ns]->floor, frustum)) { - - sectorqueue[back++] = ns; - drawingstate[ns] = 1; - } - } - } -#endif - i = sec->wallnum-1; - do - { - if ((queryid[sec->wallptr + i]) && - (!drawingstate[wall[sec->wallptr + i].nextsector])) - { - // REAP - result = 0; - if (doquery && (queryid[sec->wallptr + i] != 0xFFFFFFFF)) - { - glGetQueryObjectiv(queryid[sec->wallptr + i], - GL_QUERY_RESULT, - &result); - glDeleteQueries(1, &queryid[sec->wallptr + i]); - } else if (queryid[sec->wallptr + i] == 0xFFFFFFFF) - result = 1; - - queryid[sec->wallptr + i] = 0; - - if (result || !doquery) - { - sectorqueue[back++] = wall[sec->wallptr + i].nextsector; - drawingstate[wall[sec->wallptr + i].nextsector] = 1; - } - } else if (queryid[sec->wallptr + i] && - queryid[sec->wallptr + i] != 0xFFFFFFFF) - { - glDeleteQueries(1, &queryid[sec->wallptr + i]); - queryid[sec->wallptr + i] = 0; - } - } - while (--i >= 0); - - front++; - } - - polymer_emptybuckets(); - - // do the actual shaded drawing -// overridematerial = 0xFFFFFFFF; - - // go through the sector queue again -// front = 0; -// while (front < back) -// { -// sec = §or[sectorqueue[front]]; -// -// polymer_drawsector(sectorqueue[front]); -// -// i = 0; -// while (i < sec->wallnum) -// { -// polymer_drawwall(sectorqueue[front], sec->wallptr + i); -// -// i++; -// } -// -// front++; -// } - - i = mirrorcount-1; - while (i >= 0) - { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prrts[0].fbo); - glPushAttrib(GL_VIEWPORT_BIT); - glViewport(windowxy1.x, ydim-(windowxy2.y+1),windowxy2.x-windowxy1.x+1, windowxy2.y-windowxy1.y+1); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - Bmemcpy(localskymodelviewmatrix, curskymodelviewmatrix, sizeof(GLfloat) * 16); - curskymodelviewmatrix = localskymodelviewmatrix; - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - plane[0] = mirrorlist[i].plane->plane[0]; - plane[1] = mirrorlist[i].plane->plane[1]; - plane[2] = mirrorlist[i].plane->plane[2]; - plane[3] = mirrorlist[i].plane->plane[3]; - - glClipPlane(GL_CLIP_PLANE0, plane); - polymer_inb4mirror(mirrorlist[i].plane->buffer, mirrorlist[i].plane->plane); - SWITCH_CULL_DIRECTION; - //glEnable(GL_CLIP_PLANE0); - - if (mirrorlist[i].wallnum >= 0) - renderPrepareMirror(globalposx, globalposy, qglobalang, - mirrorlist[i].wallnum, &gx, &gy, &viewangle); - - gx = globalposx; - gy = globalposy; - gz = globalposz; - - // map the player pos from build to polymer - px = globalposy; - py = -globalposz / 16; - pz = -globalposx; - - // calculate new player position on the other side of the mirror - // this way the basic build visibility shit can be used (wallvisible) - coeff = mirrorlist[i].plane->plane[0] * px + - mirrorlist[i].plane->plane[1] * py + - mirrorlist[i].plane->plane[2] * pz + - mirrorlist[i].plane->plane[3]; - - coeff /= (float)(mirrorlist[i].plane->plane[0] * mirrorlist[i].plane->plane[0] + - mirrorlist[i].plane->plane[1] * mirrorlist[i].plane->plane[1] + - mirrorlist[i].plane->plane[2] * mirrorlist[i].plane->plane[2]); - - px = (int32_t)(-coeff*mirrorlist[i].plane->plane[0]*2 + px); - py = (int32_t)(-coeff*mirrorlist[i].plane->plane[1]*2 + py); - pz = (int32_t)(-coeff*mirrorlist[i].plane->plane[2]*2 + pz); - - // map back from polymer to build - set_globalpos(-pz, px, -py * 16); - - mirrors[depth++] = mirrorlist[i]; - polymer_displayrooms(mirrorlist[i].sectnum); - depth--; - - cursectormasks = localsectormasks; - cursectormaskcount = localsectormaskcount; - - set_globalpos(gx, gy, gz); - - glDisable(GL_CLIP_PLANE0); - SWITCH_CULL_DIRECTION; - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - glPopAttrib(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - - mirrorlist[i].plane->material.mirrormap = prrts[0].color; - polymer_drawplane(mirrorlist[i].plane); - mirrorlist[i].plane->material.mirrormap = 0; - - i--; - } - - spritesortcnt = localspritesortcnt; - Bmemcpy(tsprite, localtsprite, sizeof(spritetype) * spritesortcnt); - maskwallcnt = localmaskwallcnt; - Bmemcpy(maskwall, localmaskwall, sizeof(int16_t) * maskwallcnt); - - if (depth) - { - set_globalang(viewangle); - - if (mirrors[depth - 1].plane) - display_mirror = 1; - polymer_animatesprites(); - if (mirrors[depth - 1].plane) - display_mirror = 0; - - glDisable(GL_CULL_FACE); - renderDrawMasks(); - glEnable(GL_CULL_FACE); - } - } - -static void polymer_emptybuckets(void) -{ - _prbucket *bucket = prbuckethead; - - if (pr_buckets == 0) - return; - - glBindBuffer(GL_ARRAY_BUFFER, prmapvbo); - glVertexPointer(3, GL_FLOAT, sizeof(_prvert), NULL); - glTexCoordPointer(2, GL_FLOAT, sizeof(_prvert), (GLvoid *)(3 * sizeof(GLfloat))); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prindexringvbo); - - uint32_t indexcount = 0; - while (bucket != NULL) - { - indexcount += bucket->count; - - bucket = bucket->next; - } - - // ensure space in index ring, wrap otherwise - if (indexcount + prindexringoffset >= (unsigned)prindexringsize) - { - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - prindexring = (GLuint *)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, prindexringsize * sizeof(GLuint), GL_MAP_INVALIDATE_BUFFER_BIT | prindexringmapflags); - prindexringoffset = 0; - } - - // put indices in the ring, all at once - bucket = prbuckethead; - - while (bucket != NULL) - { - if (bucket->count == 0) - { - bucket = bucket->next; - continue; - } - - memcpy(&prindexring[prindexringoffset], bucket->indices, bucket->count * sizeof(GLuint)); - - bucket->indiceoffset = (GLuint*)(prindexringoffset * sizeof(GLuint)); - - prindexringoffset += bucket->count; - - bucket = bucket->next; - } - - bucket = prbuckethead; - - while (bucket != NULL) - { - if (bucket->count == 0) - { - bucket = bucket->next; - continue; - } - - int32_t materialbits = polymer_bindmaterial(&bucket->material, NULL, 0); - - glDrawElements(GL_TRIANGLES, bucket->count, GL_UNSIGNED_INT, bucket->indiceoffset); - - polymer_unbindmaterial(materialbits); - - bucket->count = 0; - - bucket = bucket->next; - } - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - prcanbucket = 0; -} - -static hashtable_t h_buckets = { 2048, NULL }; - -static _prbucket* polymer_findbucket(int16_t tilenum, char pal) -{ - char propstr[16]; - - Bsprintf(propstr, "%d_%d", tilenum, pal); - - _prbucket *bucketptr = prbuckethead ? (_prbucket *)hash_find(&h_buckets, propstr) : NULL; - - // find bucket - - // no buckets or no bucket found, create one - if (bucketptr == NULL || (intptr_t)bucketptr == -1) - { - bucketptr = (_prbucket *)Xmalloc(sizeof (_prbucket)); - - if (h_buckets.items == NULL) - hash_init(&h_buckets); - - // insert, since most likely to use same pattern next frame - // will need to reorder by MRU first every once in a while - // or move to hashing lookup - bucketptr->next = prbuckethead; - prbuckethead = bucketptr; - - bucketptr->tilenum = tilenum; - bucketptr->pal = pal; - - bucketptr->invalidmaterial = 1; - - bucketptr->count = 0; - bucketptr->buffersize = 1024; - bucketptr->indices = (GLuint *)Xmalloc(bucketptr->buffersize * sizeof(GLuint)); - - hash_add(&h_buckets, propstr, (intptr_t)bucketptr, 1); - } - - return bucketptr; -} - -static void polymer_bucketplane(_prplane* plane) -{ - _prbucket *bucketptr = plane->bucket; - uint32_t neededindicecount; - int32_t i; - - // we don't keep buffers for quads - neededindicecount = (plane->indicescount == 0) ? 6 : plane->indicescount; - - // ensure size - while (bucketptr->count + neededindicecount >= bucketptr->buffersize) - { - bucketptr->buffersize *= 2; - bucketptr->indices = (GLuint *)Xrealloc(bucketptr->indices, bucketptr->buffersize * sizeof(GLuint)); - } - - // queue indices - i = 0; - - if (plane->indicescount > 0) - { - while (i < plane->indicescount) - { - bucketptr->indices[bucketptr->count] = plane->indices[i] + plane->mapvbo_vertoffset; - bucketptr->count++; - i++; - } - } - else - { - static const uint32_t quadindices[6] = { 0, 1, 2, 0, 2, 3 }; - - while (i < 6) - { - bucketptr->indices[bucketptr->count] = quadindices[i] + plane->mapvbo_vertoffset; - bucketptr->count++; - i++; - } - } -} - -static void polymer_drawplane(_prplane* plane) -{ - int32_t materialbits; - - if (pr_nullrender >= 1) return; - - // debug code for drawing plane inverse TBN -// glDisable(GL_TEXTURE_2D); -// glBegin(GL_LINES); -// glColor4f(1.0, 0.0, 0.0, 1.0); -// glVertex3f(plane->buffer[0], -// plane->buffer[1], -// plane->buffer[2]); -// glVertex3f(plane->buffer[0] + plane->t[0] * 50, -// plane->buffer[1] + plane->t[1] * 50, -// plane->buffer[2] + plane->t[2] * 50); -// glColor4f(0.0, 1.0, 0.0, 1.0); -// glVertex3f(plane->buffer[0], -// plane->buffer[1], -// plane->buffer[2]); -// glVertex3f(plane->buffer[0] + plane->b[0] * 50, -// plane->buffer[1] + plane->b[1] * 50, -// plane->buffer[2] + plane->b[2] * 50); -// glColor4f(0.0, 0.0, 1.0, 1.0); -// glVertex3f(plane->buffer[0], -// plane->buffer[1], -// plane->buffer[2]); -// glVertex3f(plane->buffer[0] + plane->n[0] * 50, -// plane->buffer[1] + plane->n[1] * 50, -// plane->buffer[2] + plane->n[2] * 50); -// glEnd(); -// glEnable(GL_TEXTURE_2D); - - // debug code for drawing plane normals -// glDisable(GL_TEXTURE_2D); -// glBegin(GL_LINES); -// glColor4f(1.0, 1.0, 1.0, 1.0); -// glVertex3f(plane->buffer[0], -// plane->buffer[1], -// plane->buffer[2]); -// glVertex3f(plane->buffer[0] + plane->plane[0] * 50, -// plane->buffer[1] + plane->plane[1] * 50, -// plane->buffer[2] + plane->plane[2] * 50); -// glEnd(); -// glEnable(GL_TEXTURE_2D); - - if (pr_buckets && pr_vbos > 0 && prcanbucket && plane->bucket) - { - polymer_bucketplane(plane); - return; - } - - glNormal3f((float)(plane->plane[0]), (float)(plane->plane[1]), (float)(plane->plane[2])); - - GLuint planevbo; - GLintptr geomfbooffset; - - if (plane->mapvbo_vertoffset != (uint32_t)-1) - { - planevbo = prmapvbo; - geomfbooffset = plane->mapvbo_vertoffset * sizeof(_prvert); - } - else - { - planevbo = plane->vbo; - geomfbooffset = 0; - } - - if (planevbo && (pr_vbos > 0)) - { - glBindBuffer(GL_ARRAY_BUFFER, planevbo); - glVertexPointer(3, GL_FLOAT, sizeof(_prvert), (GLvoid *)(geomfbooffset)); - glTexCoordPointer(2, GL_FLOAT, sizeof(_prvert), (GLvoid *)(geomfbooffset + (3 * sizeof(GLfloat)))); - if (plane->indices) - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane->ivbo); - } else { - glVertexPointer(3, GL_FLOAT, sizeof(_prvert), &plane->buffer->x); - glTexCoordPointer(2, GL_FLOAT, sizeof(_prvert), &plane->buffer->u); - } - - curlight = 0; - do { - materialbits = polymer_bindmaterial(&plane->material, plane->lights, plane->lightcount); - - if (materialbits & prprogrambits[PR_BIT_NORMAL_MAP].bit) - { - glVertexAttrib3fv(prprograms[materialbits].attrib_T, &plane->tbn[0][0]); - glVertexAttrib3fv(prprograms[materialbits].attrib_B, &plane->tbn[1][0]); - glVertexAttrib3fv(prprograms[materialbits].attrib_N, &plane->tbn[2][0]); - } - - if (plane->indices) - { - if (planevbo && (pr_vbos > 0)) - glDrawElements(GL_TRIANGLES, plane->indicescount, GL_UNSIGNED_SHORT, NULL); - else - glDrawElements(GL_TRIANGLES, plane->indicescount, GL_UNSIGNED_SHORT, plane->indices); - } else - glDrawArrays(GL_QUADS, 0, 4); - - polymer_unbindmaterial(materialbits); - - if (plane->lightcount && (!depth || mirrors[depth-1].plane)) - prlights[plane->lights[curlight]].flags.isinview = 1; - - curlight++; - } while ((curlight < plane->lightcount) && (curlight < pr_maxlightpasses) && (!depth || mirrors[depth-1].plane)); - - if (planevbo && (pr_vbos > 0)) - { - glBindBuffer(GL_ARRAY_BUFFER, 0); - if (plane->indices) - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } -} - -static inline void polymer_inb4mirror(_prvert* buffer, const GLfloat* plane) -{ - float pv; - float reflectionmatrix[16]; - - pv = buffer->x * plane[0] + - buffer->y * plane[1] + - buffer->z * plane[2]; - - reflectionmatrix[0] = 1 - (2 * plane[0] * plane[0]); - reflectionmatrix[1] = -2 * plane[0] * plane[1]; - reflectionmatrix[2] = -2 * plane[0] * plane[2]; - reflectionmatrix[3] = 0; - - reflectionmatrix[4] = -2 * plane[0] * plane[1]; - reflectionmatrix[5] = 1 - (2 * plane[1] * plane[1]); - reflectionmatrix[6] = -2 * plane[1] * plane[2]; - reflectionmatrix[7] = 0; - - reflectionmatrix[8] = -2 * plane[0] * plane[2]; - reflectionmatrix[9] = -2 * plane[1] * plane[2]; - reflectionmatrix[10] = 1 - (2 * plane[2] * plane[2]); - reflectionmatrix[11] = 0; - - reflectionmatrix[12] = 2 * pv * plane[0]; - reflectionmatrix[13] = 2 * pv * plane[1]; - reflectionmatrix[14] = 2 * pv * plane[2]; - reflectionmatrix[15] = 1; - - glMultMatrixf(reflectionmatrix); - - glPushMatrix(); - glLoadMatrixf(curskymodelviewmatrix); - glMultMatrixf(reflectionmatrix); - glGetFloatv(GL_MODELVIEW_MATRIX, curskymodelviewmatrix); - glPopMatrix(); -} - -static void polymer_animatesprites(void) -{ - if (asi.animatesprites) - asi.animatesprites(globalposx, globalposy, fix16_to_int(viewangle), asi.smoothratio); -} - -static void polymer_freeboard(void) -{ - int32_t i; - - i = 0; - while (i < MAXSECTORS) - { - if (prsectors[i]) - { - Bfree(prsectors[i]->verts); - Bfree(prsectors[i]->floor.buffer); - Bfree(prsectors[i]->ceil.buffer); - Bfree(prsectors[i]->floor.indices); - Bfree(prsectors[i]->ceil.indices); - if (prsectors[i]->ceil.vbo) glDeleteBuffers(1, &prsectors[i]->ceil.vbo); - if (prsectors[i]->ceil.ivbo) glDeleteBuffers(1, &prsectors[i]->ceil.ivbo); - if (prsectors[i]->floor.vbo) glDeleteBuffers(1, &prsectors[i]->floor.vbo); - if (prsectors[i]->floor.ivbo) glDeleteBuffers(1, &prsectors[i]->floor.ivbo); - - DO_FREE_AND_NULL(prsectors[i]); - } - - i++; - } - - i = 0; - while (i < MAXWALLS) - { - if (prwalls[i]) - { - Bfree(prwalls[i]->bigportal); - Bfree(prwalls[i]->mask.buffer); - Bfree(prwalls[i]->over.buffer); - // Bfree(prwalls[i]->cap); - Bfree(prwalls[i]->wall.buffer); - if (prwalls[i]->wall.vbo) glDeleteBuffers(1, &prwalls[i]->wall.vbo); - if (prwalls[i]->over.vbo) glDeleteBuffers(1, &prwalls[i]->over.vbo); - if (prwalls[i]->mask.vbo) glDeleteBuffers(1, &prwalls[i]->mask.vbo); - if (prwalls[i]->stuffvbo) glDeleteBuffers(1, &prwalls[i]->stuffvbo); - - DO_FREE_AND_NULL(prwalls[i]); - } - - i++; - } - - i = 0; - while (i < MAXSPRITES) - { - if (prsprites[i]) - { - Bfree(prsprites[i]->plane.buffer); - if (prsprites[i]->plane.vbo) glDeleteBuffers(1, &prsprites[i]->plane.vbo); - DO_FREE_AND_NULL(prsprites[i]); - } - - i++; - } - - i = 0; - while (i < MAXTILES) - { - polymer_invalidateartmap(i); - i++; - } - - i = 0; - while (i < MAXBASEPALS) - { - if (prbasepalmaps[i]) - { - glDeleteTextures(1, &prbasepalmaps[i]); - prbasepalmaps[i] = 0; - } - - i++; - } - - i = 0; - while (i < MAXPALOOKUPS) - { - if (prlookups[i]) - { - glDeleteTextures(1, &prlookups[i]); - prlookups[i] = 0; - } - - i++; - } -} - -// SECTORS -static int32_t polymer_initsector(int16_t sectnum) -{ - usectortype *sec; - _prsector* s; - - if (pr_verbosity >= 2) OSD_Printf("PR : Initializing sector %i...\n", sectnum); - - sec = (usectortype *)§or[sectnum]; - s = (_prsector *)Xcalloc(1, sizeof(_prsector)); - - s->verts = (GLdouble *)Xcalloc(sec->wallnum, sizeof(GLdouble) * 3); - s->floor.buffer = (_prvert *)Xcalloc(sec->wallnum, sizeof(_prvert)); - s->floor.vertcount = sec->wallnum; - s->ceil.buffer = (_prvert *)Xcalloc(sec->wallnum, sizeof(_prvert)); - s->ceil.vertcount = sec->wallnum; - - glGenBuffers(1, &s->floor.vbo); - glGenBuffers(1, &s->ceil.vbo); - glGenBuffers(1, &s->floor.ivbo); - glGenBuffers(1, &s->ceil.ivbo); - - glBindBuffer(GL_ARRAY_BUFFER, s->floor.vbo); - glBufferData(GL_ARRAY_BUFFER, sec->wallnum * sizeof(GLfloat) * 5, NULL, mapvbousage); - - glBindBuffer(GL_ARRAY_BUFFER, s->ceil.vbo); - glBufferData(GL_ARRAY_BUFFER, sec->wallnum * sizeof(GLfloat) * 5, NULL, mapvbousage); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - - s->flags.empty = 1; // let updatesector know that everything needs to go - - prsectors[sectnum] = s; - - if (pr_verbosity >= 2) OSD_Printf("PR : Initialized sector %i.\n", sectnum); - - return 1; -} - -static int32_t polymer_updatesector(int16_t sectnum) -{ - _prsector* s; - usectortype *sec; - walltype *wal; - int32_t i, j; - int32_t ceilz, florz; - int32_t tex, tey, heidiff; - float secangcos, secangsin, scalecoef, xpancoef, ypancoef; - int32_t ang, needfloor, wallinvalidate; - int16_t curstat, curpicnum, floorpicnum, ceilingpicnum; - char curxpanning, curypanning; - _prvert* curbuffer; - - if (pr_nullrender >= 3) return 0; - - s = prsectors[sectnum]; - sec = (usectortype *)§or[sectnum]; - - secangcos = secangsin = 2; - - if (s == NULL) - { - if (pr_verbosity >= 1) OSD_Printf("PR : Can't update uninitialized sector %i.\n", sectnum); - return -1; - } - - needfloor = wallinvalidate = 0; - - // geometry - wal = &wall[sec->wallptr]; - i = 0; - while (i < sec->wallnum) - { - if ((-wal->x != s->verts[(i*3)+2])) - { - s->verts[(i*3)+2] = s->floor.buffer[i].z = s->ceil.buffer[i].z = -(float)wal->x; - needfloor = wallinvalidate = 1; - } - if ((wal->y != s->verts[i*3])) - { - s->verts[i*3] = s->floor.buffer[i].x = s->ceil.buffer[i].x = (float)wal->y; - needfloor = wallinvalidate = 1; - } - - i++; - wal = &wall[sec->wallptr + i]; - } - - if ((s->flags.empty) || - needfloor || - (sec->floorz != s->floorz) || - (sec->ceilingz != s->ceilingz) || - (sec->floorheinum != s->floorheinum) || - (sec->ceilingheinum != s->ceilingheinum)) - { - wallinvalidate = 1; - - wal = &wall[sec->wallptr]; - i = 0; - while (i < sec->wallnum) - { - getzsofslope(sectnum, wal->x, wal->y, &ceilz, &florz); - s->floor.buffer[i].y = -(float)(florz) / 16.0f; - s->ceil.buffer[i].y = -(float)(ceilz) / 16.0f; - - i++; - wal = &wall[sec->wallptr + i]; - } - - s->floorz = sec->floorz; - s->ceilingz = sec->ceilingz; - s->floorheinum = sec->floorheinum; - s->ceilingheinum = sec->ceilingheinum; - } - else if (sec->visibility != s->visibility) - wallinvalidate = 1; - - floorpicnum = sec->floorpicnum; - DO_TILE_ANIM(floorpicnum, sectnum); - ceilingpicnum = sec->ceilingpicnum; - DO_TILE_ANIM(ceilingpicnum, sectnum); - - if ((!s->flags.empty) && (!needfloor) && - (floorpicnum == s->floorpicnum_anim) && - (ceilingpicnum == s->ceilingpicnum_anim) && -#ifndef UNTRACKED_STRUCTS - (s->trackedrev == sectorchanged[sectnum])) -#else - !Bmemcmp(&s->ceilingstat, &sec->ceilingstat, offsetof(sectortype, visibility) - offsetof(sectortype, ceilingstat))) -#endif - goto attributes; - - wal = &wall[sec->wallptr]; - i = 0; - while (i < sec->wallnum) - { - j = 2; - curstat = sec->floorstat; - curbuffer = s->floor.buffer; - curpicnum = floorpicnum; - curxpanning = sec->floorxpanning; - curypanning = sec->floorypanning; - - while (j) - { - if (j == 1) - { - curstat = sec->ceilingstat; - curbuffer = s->ceil.buffer; - curpicnum = ceilingpicnum; - curxpanning = sec->ceilingxpanning; - curypanning = sec->ceilingypanning; - } - - if (!waloff[curpicnum]) - tileLoad(curpicnum); - - if (((sec->floorstat & 64) || (sec->ceilingstat & 64)) && - ((secangcos == 2) && (secangsin == 2))) - { - ang = (getangle(wall[wal->point2].x - wal->x, wall[wal->point2].y - wal->y) + 512) & 2047; - secangcos = (float)(sintable[(ang+512)&2047]) / 16383.0f; - secangsin = (float)(sintable[ang&2047]) / 16383.0f; - } - - // relative texturing - if (curstat & 64) - { - xpancoef = (float)(wal->x - wall[sec->wallptr].x); - ypancoef = (float)(wall[sec->wallptr].y - wal->y); - - tex = (int32_t)(xpancoef * secangsin + ypancoef * secangcos); - tey = (int32_t)(xpancoef * secangcos - ypancoef * secangsin); - } else { - tex = wal->x; - tey = -wal->y; - } - - if ((curstat & (2+64)) == (2+64)) - { - heidiff = (int32_t)(curbuffer[i].y - curbuffer[0].y); - // don't forget the sign, tey could be negative with concave sectors - if (tey >= 0) - tey = (int32_t)sqrt((double)((tey * tey) + (heidiff * heidiff))); - else - tey = -(int32_t)sqrt((double)((tey * tey) + (heidiff * heidiff))); - } - - if (curstat & 4) - swaplong(&tex, &tey); - - if (curstat & 16) tex = -tex; - if (curstat & 32) tey = -tey; - - scalecoef = (curstat & 8) ? 8.0f : 16.0f; - - if (curxpanning) - { - xpancoef = (float)(pow2long[picsiz[curpicnum] & 15]); - xpancoef *= (float)(curxpanning) / (256.0f * (float)(tilesiz[curpicnum].x)); - } - else - xpancoef = 0; - - if (curypanning) - { - ypancoef = (float)(pow2long[picsiz[curpicnum] >> 4]); - ypancoef *= (float)(curypanning) / (256.0f * (float)(tilesiz[curpicnum].y)); - } - else - ypancoef = 0; - - curbuffer[i].u = ((float)(tex) / (scalecoef * tilesiz[curpicnum].x)) + xpancoef; - curbuffer[i].v = ((float)(tey) / (scalecoef * tilesiz[curpicnum].y)) + ypancoef; - - j--; - } - i++; - wal = &wall[sec->wallptr + i]; - } - - s->floorxpanning = sec->floorxpanning; - s->ceilingxpanning = sec->ceilingxpanning; - s->floorypanning = sec->floorypanning; - s->ceilingypanning = sec->ceilingypanning; -#ifndef UNTRACKED_STRUCTS - s->trackedrev = sectorchanged[sectnum]; -#endif - - i = -1; - -attributes: - if ((pr_vbos > 0) && ((i == -1) || (wallinvalidate))) - { - if (pr_vbos > 0) - { - if (pr_nullrender < 2) - { - /*glBindBuffer(GL_ARRAY_BUFFER, s->floor.vbo); - glBufferSubData(GL_ARRAY_BUFFER, 0, sec->wallnum * sizeof(GLfloat)* 5, s->floor.buffer); - glBindBuffer(GL_ARRAY_BUFFER, s->ceil.vbo); - glBufferSubData(GL_ARRAY_BUFFER, 0, sec->wallnum * sizeof(GLfloat)* 5, s->ceil.buffer); - */ - - s->floor.mapvbo_vertoffset = sec->wallptr * 2; - s->ceil.mapvbo_vertoffset = s->floor.mapvbo_vertoffset + sec->wallnum; - - GLintptr sector_offset = s->floor.mapvbo_vertoffset * sizeof(_prvert); - GLsizeiptr cur_sector_size = sec->wallnum * sizeof(_prvert); - glBindBuffer(GL_ARRAY_BUFFER, prmapvbo); - // floor - glBufferSubData(GL_ARRAY_BUFFER, sector_offset, cur_sector_size, s->floor.buffer); - // ceiling - glBufferSubData(GL_ARRAY_BUFFER, sector_offset + cur_sector_size, cur_sector_size, s->ceil.buffer); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - } - else - { - s->floor.mapvbo_vertoffset = -1; - s->ceil.mapvbo_vertoffset = -1; - } - } - - if ((!s->flags.empty) && (!s->flags.invalidtex) && - (floorpicnum == s->floorpicnum_anim) && - (ceilingpicnum == s->ceilingpicnum_anim) && - !Bmemcmp(&s->ceilingstat, &sec->ceilingstat, offsetof(sectortype, visibility) - offsetof(sectortype, ceilingstat))) - goto finish; - - s->floor.bucket = polymer_getbuildmaterial(&s->floor.material, floorpicnum, sec->floorpal, sec->floorshade, sec->visibility, (sec->floorstat & 384) ? DAMETH_MASK : DAMETH_NOMASK); - - if (sec->floorstat & 256) { - if (sec->floorstat & 128) { - s->floor.material.diffusemodulation[3] = 0x55; - } else { - s->floor.material.diffusemodulation[3] = 0xAA; - } - } - - s->ceil.bucket = polymer_getbuildmaterial(&s->ceil.material, ceilingpicnum, sec->ceilingpal, sec->ceilingshade, sec->visibility, (sec->ceilingstat & 384) ? DAMETH_MASK : DAMETH_NOMASK); - - if (sec->ceilingstat & 256) { - if (sec->ceilingstat & 128) { - s->ceil.material.diffusemodulation[3] = 0x55; - } else { - s->ceil.material.diffusemodulation[3] = 0xAA; - } - } - - s->flags.invalidtex = 0; - - // copy ceilingstat through visibility members - Bmemcpy(&s->ceilingstat, &sec->ceilingstat, offsetof(sectortype, visibility) - offsetof(sectortype, ceilingstat)); - s->floorpicnum_anim = floorpicnum; - s->ceilingpicnum_anim = ceilingpicnum; - -finish: - - if (needfloor) - { - polymer_buildfloor(sectnum); - if ((pr_vbos > 0)) - { - if (pr_nullrender < 2) - { - if (s->oldindicescount < s->indicescount) - { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->floor.ivbo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, s->indicescount * sizeof(GLushort), NULL, mapvbousage); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->ceil.ivbo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, s->indicescount * sizeof(GLushort), NULL, mapvbousage); - s->oldindicescount = s->indicescount; - } - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->floor.ivbo); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, s->indicescount * sizeof(GLushort), s->floor.indices); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->ceil.ivbo); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, s->indicescount * sizeof(GLushort), s->ceil.indices); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - } - } - - if (wallinvalidate) - { - s->invalidid++; - polymer_invalidatesectorlights(sectnum); - polymer_computeplane(&s->floor); - polymer_computeplane(&s->ceil); - } - - s->flags.empty = 0; - s->flags.uptodate = 1; - - if (pr_verbosity >= 3) OSD_Printf("PR : Updated sector %i.\n", sectnum); - - return 0; -} - -void PR_CALLBACK polymer_tesserror(GLenum error) -{ - /* This callback is called by the tesselator whenever it raises an error. - GLU_TESS_ERROR6 is the "no error"/"null" error spam in e1l1 and others. */ - - if (pr_verbosity >= 1 && error != GLU_TESS_ERROR6) OSD_Printf("PR : Tesselation error number %i reported : %s.\n", error, bgluErrorString(errno)); -} - -void PR_CALLBACK polymer_tessedgeflag(GLenum error) -{ - // Passing an edgeflag callback forces the tesselator to output a triangle list - UNREFERENCED_PARAMETER(error); -} - -void PR_CALLBACK polymer_tessvertex(void* vertex, void* sector) -{ - _prsector* s; - - s = (_prsector*)sector; - - if (s->curindice >= s->indicescount) - { - if (pr_verbosity >= 2) OSD_Printf("PR : Indice overflow, extending the indices list... !\n"); - s->indicescount++; - s->floor.indices = (GLushort *)Xrealloc(s->floor.indices, s->indicescount * sizeof(GLushort)); - s->ceil.indices = (GLushort *)Xrealloc(s->ceil.indices, s->indicescount * sizeof(GLushort)); - } - s->ceil.indices[s->curindice] = (intptr_t)vertex; - s->curindice++; -} - -static int32_t polymer_buildfloor(int16_t sectnum) -{ - // This function tesselates the floor/ceiling of a sector and stores the triangles in a display list. - _prsector* s; - usectortype *sec; - intptr_t i; - - if (pr_verbosity >= 2) OSD_Printf("PR : Tesselating floor of sector %i...\n", sectnum); - - s = prsectors[sectnum]; - sec = (usectortype *)§or[sectnum]; - - if (s == NULL) - return -1; - - if (s->floor.indices == NULL) - { - s->indicescount = (max(3, sec->wallnum) - 2) * 3; - s->floor.indices = (GLushort *)Xcalloc(s->indicescount, sizeof(GLushort)); - s->ceil.indices = (GLushort *)Xcalloc(s->indicescount, sizeof(GLushort)); - } - - s->curindice = 0; - - bgluTessCallback(prtess, GLU_TESS_VERTEX_DATA, (void (PR_CALLBACK *)(void))polymer_tessvertex); - bgluTessCallback(prtess, GLU_TESS_EDGE_FLAG, (void (PR_CALLBACK *)(void))polymer_tessedgeflag); - bgluTessCallback(prtess, GLU_TESS_ERROR, (void (PR_CALLBACK *)(void))polymer_tesserror); - - bgluTessProperty(prtess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE); - - bgluTessBeginPolygon(prtess, s); - bgluTessBeginContour(prtess); - - i = 0; - while (i < sec->wallnum) - { - bgluTessVertex(prtess, s->verts + (3 * i), (void *)i); - if ((i != (sec->wallnum - 1)) && ((sec->wallptr + i) > wall[sec->wallptr + i].point2)) - { - bgluTessEndContour(prtess); - bgluTessBeginContour(prtess); - } - i++; - } - bgluTessEndContour(prtess); - bgluTessEndPolygon(prtess); - - i = 0; - while (i < s->indicescount) - { - s->floor.indices[s->indicescount - i - 1] = s->ceil.indices[i]; - - i++; - } - s->floor.indicescount = s->ceil.indicescount = s->indicescount; - - if (pr_verbosity >= 2) OSD_Printf("PR : Tesselated floor of sector %i.\n", sectnum); - - return 1; -} - -static void polymer_drawsector(int16_t sectnum, int32_t domasks) -{ - usectortype *sec; - _prsector* s; - GLubyte oldcolor[4]; - int32_t draw; - int32_t queuedmask; - - if (pr_verbosity >= 3) OSD_Printf("PR : Drawing sector %i...\n", sectnum); - - sec = (usectortype *)§or[sectnum]; - s = prsectors[sectnum]; - - queuedmask = FALSE; - - // If you're thinking of 'optimizing' the following logic, you'd better - // provide compelling evidence that the generated code is more efficient - // than what GCC can come up with on its own. - - draw = TRUE; - // Draw masks regardless; avoid all non-masks TROR links - if (sec->floorstat & 384) { - draw = domasks; - } else if (yax_getbunch(sectnum, YAX_FLOOR) >= 0) { - draw = FALSE; - } - // Parallaxed - if (sec->floorstat & 1) { - draw = FALSE; - } - - if (draw || (searchit == 2)) { - if (searchit == 2) { - polymer_drawsearchplane(&s->floor, oldcolor, 0x02, (GLubyte *) §num); - } - else { - calc_and_apply_fog(sec->floorpicnum, fogshade(sec->floorshade, sec->floorpal), - sec->visibility, get_floor_fogpal(sec)); - polymer_drawplane(&s->floor); - } - } else if (!domasks && cursectormaskcount && sec->floorstat & 384) { - // If we just skipped a mask, queue it for later - cursectormasks[(*cursectormaskcount)++] = sectnum; - // Don't queue it twice if the ceiling is also a mask, though. - queuedmask = TRUE; - } - - draw = TRUE; - // Draw masks regardless; avoid all non-masks TROR links - if (sec->ceilingstat & 384) { - draw = domasks; - } else if (yax_getbunch(sectnum, YAX_CEILING) >= 0) { - draw = FALSE; - } - // Parallaxed - if (sec->ceilingstat & 1) { - draw = FALSE; - } - - if (draw || (searchit == 2)) { - if (searchit == 2) { - polymer_drawsearchplane(&s->ceil, oldcolor, 0x01, (GLubyte *) §num); - } - else { - calc_and_apply_fog(sec->ceilingpicnum, fogshade(sec->ceilingshade, sec->ceilingpal), - sec->visibility, get_ceiling_fogpal(sec)); - polymer_drawplane(&s->ceil); - } - } else if (!domasks && !queuedmask && cursectormaskcount && - (sec->ceilingstat & 384)) { - // If we just skipped a mask, queue it for later - cursectormasks[(*cursectormaskcount)++] = sectnum; - } - - if (pr_verbosity >= 3) OSD_Printf("PR : Finished drawing sector %i...\n", sectnum); -} - -// WALLS -static int32_t polymer_initwall(int16_t wallnum) -{ - _prwall *w; - - if (pr_verbosity >= 2) OSD_Printf("PR : Initializing wall %i...\n", wallnum); - - w = (_prwall *)Xcalloc(1, sizeof(_prwall)); - - if (w->mask.buffer == NULL) { - w->mask.buffer = (_prvert *)Xmalloc(4 * sizeof(_prvert)); - w->mask.vertcount = 4; - } - if (w->bigportal == NULL) - w->bigportal = (GLfloat *)Xmalloc(4 * sizeof(GLfloat) * 5); - //if (w->cap == NULL) - // w->cap = (GLfloat *)Xmalloc(4 * sizeof(GLfloat) * 3); - - glGenBuffers(1, &w->wall.vbo); - glGenBuffers(1, &w->over.vbo); - glGenBuffers(1, &w->mask.vbo); - glGenBuffers(1, &w->stuffvbo); - - glBindBuffer(GL_ARRAY_BUFFER, w->wall.vbo); - glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(GLfloat) * 5, NULL, mapvbousage); - - glBindBuffer(GL_ARRAY_BUFFER, w->over.vbo); - glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(GLfloat) * 5, NULL, mapvbousage); - - glBindBuffer(GL_ARRAY_BUFFER, w->mask.vbo); - glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(GLfloat) * 5, NULL, mapvbousage); - - glBindBuffer(GL_ARRAY_BUFFER, w->stuffvbo); - glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat) * 5, NULL, mapvbousage); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - - w->flags.empty = 1; - - prwalls[wallnum] = w; - - if (pr_verbosity >= 2) OSD_Printf("PR : Initialized wall %i.\n", wallnum); - - return 1; -} - -// TODO: r_npotwallmode. Needs polymost_is_npotmode() handling among others. -#define DAMETH_WALL 0 - -static float calc_ypancoef(char curypanning, int16_t curpicnum, int32_t dopancor) -{ -#ifdef NEW_MAP_FORMAT - if (g_loadedMapVersion >= 10) - return curypanning / 256.0f; -#endif - { - float ypancoef = (float)(pow2long[picsiz[curpicnum] >> 4]); - - if (ypancoef < tilesiz[curpicnum].y) - ypancoef *= 2; - - if (dopancor) - { - int32_t yoffs = Blrintf((ypancoef - tilesiz[curpicnum].y) * (255.0f / ypancoef)); - if (curypanning > 256 - yoffs) - curypanning -= yoffs; - } - - ypancoef *= (float)curypanning / (256.0f * (float)tilesiz[curpicnum].y); - - return ypancoef; - } -} - -#define NBYTES_WALL_CSTAT_THROUGH_YPANNING \ - (offsetof(walltype, ypanning)+sizeof(wall[0].ypanning) - offsetof(walltype, cstat)) - -static void polymer_updatewall(int16_t wallnum) -{ - int16_t nwallnum, nnwallnum, curpicnum, wallpicnum, walloverpicnum, nwallpicnum; - char curxpanning, curypanning, underwall, overwall, curpal; - int8_t curshade; - walltype *wal; - sectortype *sec, *nsec; - _prwall *w; - _prsector *s, *ns; - int32_t xref, yref; - float ypancoef, dist; - int32_t i; - uint32_t invalid; - int32_t sectofwall = sectorofwall(wallnum); - - if (pr_nullrender >= 3) return; - - // yes, this function is messy and unefficient - // it also works, bitches - sec = §or[sectofwall]; - - if (sectofwall < 0 || sectofwall >= numsectors || - wallnum < 0 || wallnum > numwalls || - sec->wallptr > wallnum || wallnum >= (sec->wallptr + sec->wallnum)) - return; // yay, corrupt map - - wal = &wall[wallnum]; - nwallnum = wal->nextwall; - - w = prwalls[wallnum]; - s = prsectors[sectofwall]; - invalid = s->invalidid; - if (nwallnum >= 0 && nwallnum < numwalls && wal->nextsector >= 0 && wal->nextsector < numsectors) - { - ns = prsectors[wal->nextsector]; - invalid += ns->invalidid; - nsec = §or[wal->nextsector]; - } - else - { - ns = NULL; - nsec = NULL; - } - - if (w->wall.buffer == NULL) { - w->wall.buffer = (_prvert *)Xcalloc(4, sizeof(_prvert)); // XXX - w->wall.vertcount = 4; - } - - wallpicnum = wal->picnum; - DO_TILE_ANIM(wallpicnum, wallnum+16384); - - walloverpicnum = wal->overpicnum; - if (walloverpicnum>=0) - DO_TILE_ANIM(walloverpicnum, wallnum+16384); - - if (nwallnum >= 0 && nwallnum < numwalls) - { - nwallpicnum = wall[nwallnum].picnum; - DO_TILE_ANIM(nwallpicnum, wallnum+16384); - } - else - nwallpicnum = 0; - - if ((!w->flags.empty) && (!w->flags.invalidtex) && - (w->invalidid == invalid) && - (wallpicnum == w->picnum_anim) && - (walloverpicnum == w->overpicnum_anim) && -#ifndef UNTRACKED_STRUCTS - (w->trackedrev == wallchanged[wallnum]) && -#else - !Bmemcmp(&wal->cstat, &w->cstat, NBYTES_WALL_CSTAT_THROUGH_YPANNING) && -#endif - ((nwallnum < 0 || nwallnum > numwalls) || - ((nwallpicnum == w->nwallpicnum) && - (wall[nwallnum].xpanning == w->nwallxpanning) && - (wall[nwallnum].ypanning == w->nwallypanning) && - (wall[nwallnum].cstat == w->nwallcstat) && - (wall[nwallnum].shade == w->nwallshade)))) - { - w->flags.uptodate = 1; - return; // screw you guys I'm going home - } - else - { - w->invalidid = invalid; - - Bmemcpy(&w->cstat, &wal->cstat, NBYTES_WALL_CSTAT_THROUGH_YPANNING); - - w->picnum_anim = wallpicnum; - w->overpicnum_anim = walloverpicnum; -#ifndef UNTRACKED_STRUCTS - w->trackedrev = wallchanged[wallnum]; -#endif - if (nwallnum >= 0 && nwallnum < numwalls) - { - w->nwallpicnum = nwallpicnum; - w->nwallxpanning = wall[nwallnum].xpanning; - w->nwallypanning = wall[nwallnum].ypanning; - w->nwallcstat = wall[nwallnum].cstat; - w->nwallshade = wall[nwallnum].shade; - } - } - - w->underover = underwall = overwall = 0; - - if (wal->cstat & 8) - xref = 1; - else - xref = 0; - - if ((unsigned)wal->nextsector >= (unsigned)numsectors || !ns) - { - Bmemcpy(w->wall.buffer, &s->floor.buffer[wallnum - sec->wallptr], sizeof(GLfloat) * 3); - Bmemcpy(&w->wall.buffer[1], &s->floor.buffer[wal->point2 - sec->wallptr], sizeof(GLfloat) * 3); - Bmemcpy(&w->wall.buffer[2], &s->ceil.buffer[wal->point2 - sec->wallptr], sizeof(GLfloat) * 3); - Bmemcpy(&w->wall.buffer[3], &s->ceil.buffer[wallnum - sec->wallptr], sizeof(GLfloat) * 3); - - if (wal->nextsector < 0) - curpicnum = wallpicnum; - else - curpicnum = walloverpicnum; - - w->wall.bucket = polymer_getbuildmaterial(&w->wall.material, curpicnum, wal->pal, wal->shade, sec->visibility, DAMETH_WALL); - - if (wal->cstat & 4) - yref = sec->floorz; - else - yref = sec->ceilingz; - - if ((wal->cstat & 32) && (wal->nextsector >= 0)) - { - if ((!(wal->cstat & 2) && (wal->cstat & 4)) || ((wal->cstat & 2) && (wall[nwallnum].cstat & 4))) - yref = sec->ceilingz; - else - yref = nsec->floorz; - } - - if (wal->ypanning) - // white (but not 1-way) - ypancoef = calc_ypancoef(wal->ypanning, curpicnum, !(wal->cstat & 4)); - else - ypancoef = 0; - - i = 0; - while (i < 4) - { - if ((i == 0) || (i == 3)) - dist = (float)xref; - else - dist = (float)(xref == 0); - - w->wall.buffer[i].u = ((dist * 8.0f * wal->xrepeat) + wal->xpanning) / (float)(tilesiz[curpicnum].x); - w->wall.buffer[i].v = (-(float)(yref + (w->wall.buffer[i].y * 16)) / ((tilesiz[curpicnum].y * 2048.0f) / (float)(wal->yrepeat))) + ypancoef; - - if (wal->cstat & 256) w->wall.buffer[i].v = -w->wall.buffer[i].v; - - i++; - } - - w->underover |= 1; - } - else - { - nnwallnum = wall[nwallnum].point2; - - if ((s->floor.buffer[wallnum - sec->wallptr].y < ns->floor.buffer[nnwallnum - nsec->wallptr].y) || - (s->floor.buffer[wal->point2 - sec->wallptr].y < ns->floor.buffer[nwallnum - nsec->wallptr].y)) - underwall = 1; - - if ((underwall) || (wal->cstat & 16) || (wal->cstat & 32)) - { - int32_t refwall; - - if (s->floor.buffer[wallnum - sec->wallptr].y < ns->floor.buffer[nnwallnum - nsec->wallptr].y) - Bmemcpy(w->wall.buffer, &s->floor.buffer[wallnum - sec->wallptr], sizeof(GLfloat) * 3); - else - Bmemcpy(w->wall.buffer, &ns->floor.buffer[nnwallnum - nsec->wallptr], sizeof(GLfloat) * 3); - Bmemcpy(&w->wall.buffer[1], &s->floor.buffer[wal->point2 - sec->wallptr], sizeof(GLfloat) * 3); - Bmemcpy(&w->wall.buffer[2], &ns->floor.buffer[nwallnum - nsec->wallptr], sizeof(GLfloat) * 3); - Bmemcpy(&w->wall.buffer[3], &ns->floor.buffer[nnwallnum - nsec->wallptr], sizeof(GLfloat) * 3); - - if (wal->cstat & 2) - refwall = nwallnum; - else - refwall = wallnum; - - curpicnum = (wal->cstat & 2) ? nwallpicnum : wallpicnum; - curpal = wall[refwall].pal; - curshade = wall[refwall].shade; - curxpanning = wall[refwall].xpanning; - curypanning = wall[refwall].ypanning; - - w->wall.bucket = polymer_getbuildmaterial(&w->wall.material, curpicnum, curpal, curshade, sec->visibility, DAMETH_WALL); - - if (!(wall[refwall].cstat&4)) - yref = nsec->floorz; - else - yref = sec->ceilingz; - - if (curypanning) - // under - ypancoef = calc_ypancoef(curypanning, curpicnum, !(wall[refwall].cstat & 4)); - else - ypancoef = 0; - - i = 0; - while (i < 4) - { - if ((i == 0) || (i == 3)) - dist = (float)xref; - else - dist = (float)(xref == 0); - - w->wall.buffer[i].u = ((dist * 8.0f * wal->xrepeat) + curxpanning) / (float)(tilesiz[curpicnum].x); - w->wall.buffer[i].v = (-(float)(yref + (w->wall.buffer[i].y * 16)) / ((tilesiz[curpicnum].y * 2048.0f) / (float)(wal->yrepeat))) + ypancoef; - - if ((!(wal->cstat & 2) && (wal->cstat & 256)) || - ((wal->cstat & 2) && (wall[nwallnum].cstat & 256))) - w->wall.buffer[i].v = -w->wall.buffer[i].v; - - i++; - } - - if (underwall) - w->underover |= 1; - - Bmemcpy(w->mask.buffer, &w->wall.buffer[3], sizeof(GLfloat) * 5); - Bmemcpy(&w->mask.buffer[1], &w->wall.buffer[2], sizeof(GLfloat) * 5); - } - else - { - Bmemcpy(w->mask.buffer, &s->floor.buffer[wallnum - sec->wallptr], sizeof(GLfloat) * 5); - Bmemcpy(&w->mask.buffer[1], &s->floor.buffer[wal->point2 - sec->wallptr], sizeof(GLfloat) * 5); - } - - if ((s->ceil.buffer[wallnum - sec->wallptr].y > ns->ceil.buffer[nnwallnum - nsec->wallptr].y) || - (s->ceil.buffer[wal->point2 - sec->wallptr].y > ns->ceil.buffer[nwallnum - nsec->wallptr].y)) - overwall = 1; - - if ((overwall) || (wal->cstat & 48)) - { - if (w->over.buffer == NULL) { - w->over.buffer = (_prvert *)Xmalloc(4 * sizeof(_prvert)); - w->over.vertcount = 4; - } - - Bmemcpy(w->over.buffer, &ns->ceil.buffer[nnwallnum - nsec->wallptr], sizeof(GLfloat) * 3); - Bmemcpy(&w->over.buffer[1], &ns->ceil.buffer[nwallnum - nsec->wallptr], sizeof(GLfloat) * 3); - if (s->ceil.buffer[wal->point2 - sec->wallptr].y > ns->ceil.buffer[nwallnum - nsec->wallptr].y) - Bmemcpy(&w->over.buffer[2], &s->ceil.buffer[wal->point2 - sec->wallptr], sizeof(GLfloat) * 3); - else - Bmemcpy(&w->over.buffer[2], &ns->ceil.buffer[nwallnum - nsec->wallptr], sizeof(GLfloat) * 3); - Bmemcpy(&w->over.buffer[3], &s->ceil.buffer[wallnum - sec->wallptr], sizeof(GLfloat) * 3); - - if ((wal->cstat & 16) || (wal->overpicnum == 0)) - curpicnum = wallpicnum; - else - curpicnum = wallpicnum; - - w->over.bucket = polymer_getbuildmaterial(&w->over.material, curpicnum, wal->pal, wal->shade, sec->visibility, DAMETH_WALL); - - if (wal->cstat & 48) - { - // mask - w->mask.bucket = polymer_getbuildmaterial(&w->mask.material, walloverpicnum, wal->pal, wal->shade, sec->visibility, DAMETH_WALL | ((wal->cstat & 48) == 48 ? DAMETH_NOMASK : DAMETH_MASK)); - - if (wal->cstat & 128) - { - if (wal->cstat & 512) - w->mask.material.diffusemodulation[3] = 0x55; - else - w->mask.material.diffusemodulation[3] = 0xAA; - } - } - - if (wal->cstat & 4) - yref = sec->ceilingz; - else - yref = nsec->ceilingz; - - if (wal->ypanning) - // over - ypancoef = calc_ypancoef(wal->ypanning, curpicnum, wal->cstat & 4); - else - ypancoef = 0; - - i = 0; - while (i < 4) - { - if ((i == 0) || (i == 3)) - dist = (float)xref; - else - dist = (float)(xref == 0); - - w->over.buffer[i].u = ((dist * 8.0f * wal->xrepeat) + wal->xpanning) / (float)(tilesiz[curpicnum].x); - w->over.buffer[i].v = (-(float)(yref + (w->over.buffer[i].y * 16)) / ((tilesiz[curpicnum].y * 2048.0f) / (float)(wal->yrepeat))) + ypancoef; - - if (wal->cstat & 256) w->over.buffer[i].v = -w->over.buffer[i].v; - - i++; - } - - if (overwall) - w->underover |= 2; - - Bmemcpy(&w->mask.buffer[2], &w->over.buffer[1], sizeof(GLfloat) * 5); - Bmemcpy(&w->mask.buffer[3], &w->over.buffer[0], sizeof(GLfloat) * 5); - - if ((wal->cstat & 16) || (wal->cstat & 32)) - { - const int botSwap = (wal->cstat & 4); - - if (wal->cstat & 32) - { - // 1-sided wall - if (nsec) - yref = botSwap ? sec->ceilingz : nsec->ceilingz; - else - yref = botSwap ? sec->floorz : sec->ceilingz; - } - else - { - // masked wall - if (botSwap) - yref = min(sec->floorz, nsec->floorz); - else - yref = max(sec->ceilingz, nsec->ceilingz); - } - - curpicnum = walloverpicnum; - - if (wal->ypanning) - // mask / 1-way - ypancoef = calc_ypancoef(wal->ypanning, curpicnum, 0); - else - ypancoef = 0; - - i = 0; - while (i < 4) - { - if ((i == 0) || (i == 3)) - dist = (float)xref; - else - dist = (float)(xref == 0); - - w->mask.buffer[i].u = ((dist * 8.0f * wal->xrepeat) + wal->xpanning) / (float)(tilesiz[curpicnum].x); - w->mask.buffer[i].v = (-(float)(yref + (w->mask.buffer[i].y * 16)) / ((tilesiz[curpicnum].y * 2048.0f) / (float)(wal->yrepeat))) + ypancoef; - - if (wal->cstat & 256) w->mask.buffer[i].v = -w->mask.buffer[i].v; - - i++; - } - } - } - else - { - Bmemcpy(&w->mask.buffer[2], &s->ceil.buffer[wal->point2 - sec->wallptr], sizeof(GLfloat) * 5); - Bmemcpy(&w->mask.buffer[3], &s->ceil.buffer[wallnum - sec->wallptr], sizeof(GLfloat) * 5); - } - } - - // make sure shade color handling is correct below XXX - if (wal->nextsector < 0) - Bmemcpy(w->mask.buffer, w->wall.buffer, sizeof(_prvert) * 4); - - Bmemcpy(w->bigportal, &s->floor.buffer[wallnum - sec->wallptr], sizeof(GLfloat) * 3); - Bmemcpy(&w->bigportal[5], &s->floor.buffer[wal->point2 - sec->wallptr], sizeof(GLfloat) * 3); - Bmemcpy(&w->bigportal[10], &s->ceil.buffer[wal->point2 - sec->wallptr], sizeof(GLfloat) * 3); - Bmemcpy(&w->bigportal[15], &s->ceil.buffer[wallnum - sec->wallptr], sizeof(GLfloat) * 3); - - //Bmemcpy(&w->cap[0], &s->ceil.buffer[wallnum - sec->wallptr], sizeof(GLfloat) * 3); - //Bmemcpy(&w->cap[3], &s->ceil.buffer[wal->point2 - sec->wallptr], sizeof(GLfloat) * 3); - //Bmemcpy(&w->cap[6], &s->ceil.buffer[wal->point2 - sec->wallptr], sizeof(GLfloat) * 3); - //Bmemcpy(&w->cap[9], &s->ceil.buffer[wallnum - sec->wallptr], sizeof(GLfloat) * 3); - //w->cap[7] += 1048576; // this number is the result of 1048574 + 2 - //w->cap[10] += 1048576; // this one is arbitrary - - if (w->underover & 1) - polymer_computeplane(&w->wall); - if (w->underover & 2) - polymer_computeplane(&w->over); - polymer_computeplane(&w->mask); - - if ((pr_vbos > 0)) - { - if (pr_nullrender < 2) - { - const GLintptr thiswalloffset = prwalldataoffset + (prwalldatasize * wallnum); - const GLintptr thisoveroffset = thiswalloffset + proneplanesize; - const GLintptr thismaskoffset = thisoveroffset + proneplanesize; - glBindBuffer(GL_ARRAY_BUFFER, prmapvbo); - glBufferSubData(GL_ARRAY_BUFFER, thiswalloffset, proneplanesize, w->wall.buffer); - glBindBuffer(GL_ARRAY_BUFFER, prmapvbo); - if (w->over.buffer) - glBufferSubData(GL_ARRAY_BUFFER, thisoveroffset, proneplanesize, w->over.buffer); - glBindBuffer(GL_ARRAY_BUFFER, prmapvbo); - glBufferSubData(GL_ARRAY_BUFFER, thismaskoffset, proneplanesize, w->mask.buffer); - glBindBuffer(GL_ARRAY_BUFFER, w->stuffvbo); - glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(GLfloat)* 5, w->bigportal); - //glBufferSubData(GL_ARRAY_BUFFER, 4 * sizeof(GLfloat)* 5, 4 * sizeof(GLfloat)* 3, w->cap); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - w->wall.mapvbo_vertoffset = thiswalloffset / sizeof(_prvert); - w->over.mapvbo_vertoffset = thisoveroffset / sizeof(_prvert); - w->mask.mapvbo_vertoffset = thismaskoffset / sizeof(_prvert); - } - } - else - { - w->wall.mapvbo_vertoffset = -1; - w->over.mapvbo_vertoffset = -1; - w->mask.mapvbo_vertoffset = -1; - } - - w->flags.empty = 0; - w->flags.uptodate = 1; - w->flags.invalidtex = 0; - - if (pr_verbosity >= 3) OSD_Printf("PR : Updated wall %i.\n", wallnum); -} - -static void polymer_drawwall(int16_t sectnum, int16_t wallnum) -{ - usectortype *sec; - walltype *wal; - _prwall *w; - GLubyte oldcolor[4]; - int32_t parallaxedfloor = 0, parallaxedceiling = 0; - - if (pr_verbosity >= 3) OSD_Printf("PR : Drawing wall %i...\n", wallnum); - - sec = (usectortype *)§or[sectnum]; - wal = &wall[wallnum]; - w = prwalls[wallnum]; - - if ((sec->floorstat & 1) && (wal->nextsector >= 0) && - (sector[wal->nextsector].floorstat & 1)) - parallaxedfloor = 1; - - if ((sec->ceilingstat & 1) && (wal->nextsector >= 0) && - (sector[wal->nextsector].ceilingstat & 1)) - parallaxedceiling = 1; - - calc_and_apply_fog(wal->picnum, fogshade(wal->shade, wal->pal), sec->visibility, get_floor_fogpal(sec)); - - if ((w->underover & 1) && (!parallaxedfloor || (searchit == 2))) - { - if (searchit == 2) { - polymer_drawsearchplane(&w->wall, oldcolor, 0x05, (GLubyte *) &wallnum); - } - else - polymer_drawplane(&w->wall); - } - - if ((w->underover & 2) && (!parallaxedceiling || (searchit == 2))) - { - if (searchit == 2) { - polymer_drawsearchplane(&w->over, oldcolor, 0x00, (GLubyte *) &wallnum); - } - else - polymer_drawplane(&w->over); - } - - if ((wall[wallnum].cstat & 32) && (wall[wallnum].nextsector >= 0)) - { - if (searchit == 2) { - polymer_drawsearchplane(&w->mask, oldcolor, 0x04, (GLubyte *) &wallnum); - } - else - polymer_drawplane(&w->mask); - } - - //if (!searchit && (sector[sectnum].ceilingstat & 1) && - // ((wall[wallnum].nextsector < 0) || - // !(sector[wall[wallnum].nextsector].ceilingstat & 1))) - //{ - // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - - // if (pr_vbos) - // { - // glBindBuffer(GL_ARRAY_BUFFER, w->stuffvbo); - // glVertexPointer(3, GL_FLOAT, 0, (const GLvoid*)(4 * sizeof(GLfloat) * 5)); - // } - // else - // glVertexPointer(3, GL_FLOAT, 0, w->cap); - - // glDrawArrays(GL_QUADS, 0, 4); - - // if (pr_vbos) - // glBindBuffer(GL_ARRAY_BUFFER, 0); - - // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - //} - - if (pr_verbosity >= 3) OSD_Printf("PR : Finished drawing wall %i...\n", wallnum); -} - -// HSR -static void polymer_computeplane(_prplane* p) -{ - GLfloat vec1[5], vec2[5], norm, r;// BxN[3], NxT[3], TxB[3]; - int32_t i; - _prvert* buffer; - GLfloat* plane; - - if (p->indices && (p->indicescount < 3)) - return; // corrupt sector (E3L4, I'm looking at you) - - buffer = p->buffer; - plane = p->plane; - - i = 0; - do - { - vec1[0] = buffer[(INDICE(1))].x - buffer[(INDICE(0))].x; //x1 - vec1[1] = buffer[(INDICE(1))].y - buffer[(INDICE(0))].y; //y1 - vec1[2] = buffer[(INDICE(1))].z - buffer[(INDICE(0))].z; //z1 - vec1[3] = buffer[(INDICE(1))].u - buffer[(INDICE(0))].u; //s1 - vec1[4] = buffer[(INDICE(1))].v - buffer[(INDICE(0))].v; //t1 - - vec2[0] = buffer[(INDICE(2))].x - buffer[(INDICE(1))].x; //x2 - vec2[1] = buffer[(INDICE(2))].y - buffer[(INDICE(1))].y; //y2 - vec2[2] = buffer[(INDICE(2))].z - buffer[(INDICE(1))].z; //z2 - vec2[3] = buffer[(INDICE(2))].u - buffer[(INDICE(1))].u; //s2 - vec2[4] = buffer[(INDICE(2))].v - buffer[(INDICE(1))].v; //t2 - - polymer_crossproduct(vec2, vec1, plane); - - norm = plane[0] * plane[0] + plane[1] * plane[1] + plane[2] * plane[2]; - - // hack to work around a precision issue with slopes - if (norm >= 15000) - { - float tangent[3][3]; - double det; - - // normalize the normal/plane equation and calculate its plane norm - norm = -sqrt(norm); - norm = 1.0 / norm; - plane[0] *= norm; - plane[1] *= norm; - plane[2] *= norm; - plane[3] = -(plane[0] * buffer->x + plane[1] * buffer->y + plane[2] * buffer->z); - - // calculate T and B - r = 1.0 / (vec1[3] * vec2[4] - vec2[3] * vec1[4]); - - // tangent - tangent[0][0] = (vec2[4] * vec1[0] - vec1[4] * vec2[0]) * r; - tangent[0][1] = (vec2[4] * vec1[1] - vec1[4] * vec2[1]) * r; - tangent[0][2] = (vec2[4] * vec1[2] - vec1[4] * vec2[2]) * r; - - polymer_normalize(&tangent[0][0]); - - // bitangent - tangent[1][0] = (vec1[3] * vec2[0] - vec2[3] * vec1[0]) * r; - tangent[1][1] = (vec1[3] * vec2[1] - vec2[3] * vec1[1]) * r; - tangent[1][2] = (vec1[3] * vec2[2] - vec2[3] * vec1[2]) * r; - - polymer_normalize(&tangent[1][0]); - - // normal - tangent[2][0] = plane[0]; - tangent[2][1] = plane[1]; - tangent[2][2] = plane[2]; - - INVERT_3X3(p->tbn, det, tangent); - - break; - } - i+= (p->indices) ? 3 : 1; - } - while ((p->indices && i < p->indicescount) || - (!p->indices && i < p->vertcount)); -} - -static inline void polymer_crossproduct(const GLfloat* in_a, const GLfloat* in_b, GLfloat* out) -{ - out[0] = in_a[1] * in_b[2] - in_a[2] * in_b[1]; - out[1] = in_a[2] * in_b[0] - in_a[0] * in_b[2]; - out[2] = in_a[0] * in_b[1] - in_a[1] * in_b[0]; -} - -static inline void polymer_transformpoint(const float* inpos, float* pos, const float* matrix) -{ - pos[0] = inpos[0] * matrix[0] + - inpos[1] * matrix[4] + - inpos[2] * matrix[8] + - + matrix[12]; - pos[1] = inpos[0] * matrix[1] + - inpos[1] * matrix[5] + - inpos[2] * matrix[9] + - + matrix[13]; - pos[2] = inpos[0] * matrix[2] + - inpos[1] * matrix[6] + - inpos[2] * matrix[10] + - + matrix[14]; -} - -static inline void polymer_normalize(float* vec) -{ - double norm; - - norm = vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]; - - norm = sqrt(norm); - norm = 1.0 / norm; - vec[0] *= norm; - vec[1] *= norm; - vec[2] *= norm; -} - -static inline void polymer_pokesector(int16_t sectnum) -{ - sectortype *sec = §or[sectnum]; - _prsector *s = prsectors[sectnum]; - walltype *wal = &wall[sec->wallptr]; - int32_t i = 0; - - if (!s->flags.uptodate) - polymer_updatesector(sectnum); - - do - { - if ((wal->nextsector >= 0) && (!prsectors[wal->nextsector]->flags.uptodate)) - polymer_updatesector(wal->nextsector); - if (!prwalls[sec->wallptr + i]->flags.uptodate) - polymer_updatewall(sec->wallptr + i); - - i++; - wal = &wall[sec->wallptr + i]; - } - while (i < sec->wallnum); -} - -static void polymer_extractfrustum(GLfloat* modelview, GLfloat* projection, float* frustum) -{ - GLfloat matrix[16]; - int32_t i; - - glMatrixMode(GL_TEXTURE); - glLoadMatrixf(projection); - glMultMatrixf(modelview); - glGetFloatv(GL_TEXTURE_MATRIX, matrix); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - - i = 0; - do - { - uint32_t ii = i<<2, iii = (i<<2) + 3; - - frustum[i] = matrix[iii] + matrix[ii]; // left - frustum[i + 4] = matrix[iii] - matrix[ii]; // right - frustum[i + 8] = matrix[iii] - matrix[ii + 1]; // top - frustum[i + 12] = matrix[iii] + matrix[ii + 1]; // bottom - frustum[i + 16] = matrix[iii] - matrix[ii + 2]; // far - } - while (++i < 4); - - if (pr_verbosity >= 3) OSD_Printf("PR : Frustum extracted.\n"); -} - -static inline int32_t polymer_planeinfrustum(_prplane *plane, const float* frustum) -{ - int32_t i, j, k = -1; - i = 4; - - - do - { - int32_t ii = i * 4; - j = k = plane->vertcount - 1; - - do - { - k -= ((frustum[ii + 0] * plane->buffer[j].x + - frustum[ii + 1] * plane->buffer[j].y + - frustum[ii + 2] * plane->buffer[j].z + - frustum[ii + 3]) < 0.f); - } - while (j--); - - if (k == -1) - return 0; // OUT ! - } - while (i--); - - return 1; -} - -static inline void polymer_scansprites(int16_t sectnum, uspritetype* localtsprite, int32_t* localspritesortcnt) -{ - int32_t i; - spritetype *spr; - - for (i = headspritesect[sectnum];i >=0;i = nextspritesect[i]) - { - spr = &sprite[i]; - if ((((spr->cstat&0x8000) == 0) || (showinvisibility)) && - (spr->xrepeat > 0) && (spr->yrepeat > 0) && - (*localspritesortcnt < maxspritesonscreen)) - { - // this function's localtsprite is either the tsprite global or - // polymer_drawroom's locattsprite, so no aliasing - Bmemcpy(&localtsprite[*localspritesortcnt], spr, sizeof(spritetype)); - localtsprite[*localspritesortcnt].extra = 0; - localtsprite[(*localspritesortcnt)++].owner = i; - } - } -} - -void polymer_updatesprite(int32_t snum) -{ - int32_t xsize, ysize, i, j; - int32_t tilexoff, tileyoff, xoff, yoff, centeryoff=0; - uspritetype *tspr = tspriteptr[snum]; - float xratio, yratio, ang; - float spos[3]; - const _prvert *inbuffer; - uint8_t flipu, flipv; - _prsprite *s; - - const uint32_t cs = tspr->cstat; - const uint32_t alignmask = (cs & SPR_ALIGN_MASK); - const uint8_t flooraligned = (alignmask==SPR_FLOOR); - - if (pr_nullrender >= 3) return; - - if (pr_verbosity >= 3) OSD_Printf("PR : Updating sprite %i...\n", snum); - - int32_t const curpicnum = tspr->picnum; - - if (tspr->owner < 0 || curpicnum < 0) return; - - s = prsprites[tspr->owner]; - - if (s == NULL) - { - s = prsprites[tspr->owner] = (_prsprite *)Xcalloc(sizeof(_prsprite), 1); - - s->plane.buffer = (_prvert *)Xcalloc(4, sizeof(_prvert)); // XXX - s->plane.vertcount = 4; - s->plane.mapvbo_vertoffset = -1; - s->hash = 0xDEADBEEF; - } - - if ((tspr->cstat & 48) && (pr_vbos > 0) && !s->plane.vbo) - { - if (pr_nullrender < 2) - { - glGenBuffers(1, &s->plane.vbo); - glBindBuffer(GL_ARRAY_BUFFER, s->plane.vbo); - glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(_prvert), NULL, mapvbousage); - } - } - - if (tspr->cstat & 48 && searchit != 2) - { - uint32_t const changed = XXH32((uint8_t *) tspr, offsetof(spritetype, owner), 0xDEADBEEF); - - if (changed == s->hash) - return; - - s->hash = changed; - } - - polymer_getbuildmaterial(&s->plane.material, curpicnum, tspr->pal, tspr->shade, - sector[tspr->sectnum].visibility, DAMETH_MASK | DAMETH_CLAMPED); - - if (tspr->cstat & 2) - { - if (tspr->cstat & 512) - s->plane.material.diffusemodulation[3] = 0x55; - else - s->plane.material.diffusemodulation[3] = 0xAA; - } - - float f = s->plane.material.diffusemodulation[3] * (1.0f - spriteext[tspr->owner].alpha); - s->plane.material.diffusemodulation[3] = (GLubyte)f; - - if (searchit == 2) - { - polymer_setupdiffusemodulation(&s->plane, 0x03, (GLubyte *) &tspr->owner); - s->hash = 0xDEADBEEF; - } - - if (((tspr->cstat>>4) & 3) == 0) - xratio = (float)(tspr->xrepeat) * 0.20f; // 32 / 160 - else - xratio = (float)(tspr->xrepeat) * 0.25f; - - yratio = (float)(tspr->yrepeat) * 0.25f; - - xsize = tilesiz[curpicnum].x; - ysize = tilesiz[curpicnum].y; - - if (usehightile && h_xsize[curpicnum]) - { - xsize = h_xsize[curpicnum]; - ysize = h_ysize[curpicnum]; - } - - xsize = (int32_t)(xsize * xratio); - ysize = (int32_t)(ysize * yratio); - - tilexoff = (int32_t)tspr->xoffset; - tileyoff = (int32_t)tspr->yoffset; - tilexoff += (usehightile && h_xsize[curpicnum]) ? h_xoffs[curpicnum] : picanm[curpicnum].xofs; - tileyoff += (usehightile && h_xsize[curpicnum]) ? h_yoffs[curpicnum] : picanm[curpicnum].yofs; - - xoff = (int32_t)(tilexoff * xratio); - yoff = (int32_t)(tileyoff * yratio); - - if ((tspr->cstat & 128) && !flooraligned) - { - if (alignmask == 0) - yoff -= ysize / 2; - else - centeryoff = ysize / 2; - } - - spos[0] = (float)tspr->y; - spos[1] = -(float)(tspr->z) / 16.0f; - spos[2] = -(float)tspr->x; - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - inbuffer = vertsprite; - - { - const uint8_t xflip = !!(cs & SPR_XFLIP); - const uint8_t yflip = !!(cs & SPR_YFLIP); - - // Initially set flipu and flipv. - flipu = (xflip ^ flooraligned); - flipv = (yflip && !flooraligned); - - if (pr_billboardingmode && alignmask==0) - { - // do surgery on the face tspr to make it look like a wall sprite - tspr->cstat |= 16; - tspr->ang = (fix16_to_int(viewangle) + 1024) & 2047; - } - - if (flipu) - xoff = -xoff; - - if (yflip && alignmask!=0) - yoff = -yoff; - } - - switch (tspr->cstat & SPR_ALIGN_MASK) - { - case 0: - ang = (float)((fix16_to_int(viewangle)) & 2047) * (360.f/2048.f); - - glTranslatef(spos[0], spos[1], spos[2]); - glRotatef(-ang, 0.0f, 1.0f, 0.0f); - glRotatef(-horizang, 1.0f, 0.0f, 0.0f); - glTranslatef((float)(-xoff), (float)(yoff), 0.0f); - glScalef((float)(xsize), (float)(ysize), 1.0f); - break; - case SPR_WALL: - ang = (float)((tspr->ang + 1024) & 2047) * (360.f/2048.f); - - glTranslatef(spos[0], spos[1], spos[2]); - glRotatef(-ang, 0.0f, 1.0f, 0.0f); - glTranslatef((float)(-xoff), (float)(yoff-centeryoff), 0.0f); - glScalef((float)(xsize), (float)(ysize), 1.0f); - break; - case SPR_FLOOR: - ang = (float)((tspr->ang + 1024) & 2047) * (360.f/2048.f); - - glTranslatef(spos[0], spos[1], spos[2]); - glRotatef(-ang, 0.0f, 1.0f, 0.0f); - glTranslatef((float)(-xoff), 1.0f, (float)(yoff)); - glScalef((float)(xsize), 1.0f, (float)(ysize)); - - inbuffer = horizsprite; - break; - } - - glGetFloatv(GL_MODELVIEW_MATRIX, spritemodelview); - glPopMatrix(); - - Bmemcpy(s->plane.buffer, inbuffer, sizeof(_prvert) * 4); - - if (flipu || flipv) - { - i = 0; - do - { - if (flipu) - s->plane.buffer[i].u = - (s->plane.buffer[i].u - 1.0f) * -1.0f; - if (flipv) - s->plane.buffer[i].v = - (s->plane.buffer[i].v - 1.0f) * -1.0f; - } - while (++i < 4); - } - - i = 0; - do - polymer_transformpoint(&inbuffer[i].x, &s->plane.buffer[i].x, spritemodelview); - while (++i < 4); - - polymer_computeplane(&s->plane); - - if (pr_nullrender < 2) - { - if (alignmask && (pr_vbos > 0)) - { - glBindBuffer(GL_ARRAY_BUFFER, s->plane.vbo); - glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * sizeof(_prvert), s->plane.buffer); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - else if (s->plane.vbo) // clean up the vbo if a wall/floor sprite becomes a face sprite - { - glDeleteBuffers(1, &s->plane.vbo); - s->plane.vbo = 0; - } - } - - if (alignmask) - { - int32_t curpriority = 0; - - polymer_resetplanelights(&s->plane); - - while (curpriority < pr_maxlightpriority) - { - i = j = 0; - while (j < lightcount) - { - while (!prlights[i].flags.active) - i++; - - if (prlights[i].priority != curpriority) - { - i++; - j++; - continue; - } - - if (polymer_planeinlight(&s->plane, &prlights[i])) - polymer_addplanelight(&s->plane, i); - i++; - j++; - } - curpriority++; - } - } -} - -// SKIES -static void polymer_getsky(void) -{ - int32_t i; - - i = 0; - while (i < numsectors) - { - if (sector[i].ceilingstat & 1) - { - int32_t horizfrac; - - cursky = sector[i].ceilingpicnum; - curskypal = sector[i].ceilingpal; - curskyshade = sector[i].ceilingshade; - - getpsky(cursky, &horizfrac, NULL, NULL, NULL); - - switch (horizfrac) - { - case 0: - // psky always at same level wrt screen - curskyangmul = 0.f; - break; - case 65536: - // psky horiz follows camera horiz - curskyangmul = 1.f; - break; - default: - // sky has hard-coded parallax - curskyangmul = 1/DEFAULT_ARTSKY_ANGDIV; - break; - } - - return; - } - i++; - } -} - -void polymer_drawsky(int16_t tilenum, char palnum, int8_t shade) -{ - float pos[3]; - pthtyp* pth; - - pos[0] = fglobalposy; - pos[1] = fglobalposz * (-1.f/16.f); - pos[2] = -fglobalposx; - - glPushMatrix(); - glLoadIdentity(); - - glLoadMatrixf(curskymodelviewmatrix); - - glTranslatef(pos[0], pos[1], pos[2]); - glScalef(1000.0f, 1000.0f, 1000.0f); - - drawingskybox = 1; - pth = texcache_fetch(tilenum, 0, 0, DAMETH_NOMASK); - drawingskybox = 0; - - if (pth && (pth->flags & PTH_SKYBOX)) - polymer_drawskybox(tilenum, palnum, shade); - else - polymer_drawartsky(tilenum, palnum, shade); - - glPopMatrix(); -} - -static void polymer_initartsky(void) -{ - GLfloat halfsqrt2 = 0.70710678f; - - artskydata[0] = -1.0f; artskydata[1] = 0.0f; // 0 - artskydata[2] = -halfsqrt2; artskydata[3] = halfsqrt2; // 1 - artskydata[4] = 0.0f; artskydata[5] = 1.0f; // 2 - artskydata[6] = halfsqrt2; artskydata[7] = halfsqrt2; // 3 - artskydata[8] = 1.0f; artskydata[9] = 0.0f; // 4 - artskydata[10] = halfsqrt2; artskydata[11] = -halfsqrt2; // 5 - artskydata[12] = 0.0f; artskydata[13] = -1.0f; // 6 - artskydata[14] = -halfsqrt2; artskydata[15] = -halfsqrt2; // 7 -} - -static void polymer_drawartsky(int16_t tilenum, char palnum, int8_t shade) -{ - pthtyp* pth; - GLuint glpics[PSKYOFF_MAX+1]; - GLfloat glcolors[PSKYOFF_MAX+1][3]; - int32_t i, j; - GLfloat height = 2.45f / 2.0f; - - int32_t dapskybits; - const int8_t *dapskyoff = getpsky(tilenum, NULL, &dapskybits, NULL, NULL); - const int32_t numskytilesm1 = (1<= MAXTILES) - picnum = MAXTILES-1; - - DO_TILE_ANIM(picnum, 0); - if (!waloff[picnum]) - tileLoad(picnum); - pth = texcache_fetch(picnum, palnum, 0, DAMETH_NOMASK); - glpics[i] = pth ? pth->glpic : 0; - - glcolors[i][0] = glcolors[i][1] = glcolors[i][2] = getshadefactor(shade); - - if (pth) - { - // tinting - polytintflags_t const tintflags = hictinting[palnum].f; - if (!(tintflags & HICTINT_PRECOMPUTED)) - { - if (pth->flags & PTH_HIGHTILE) - { - if (pth->palnum != palnum || (pth->effects & HICTINT_IN_MEMORY) || (tintflags & HICTINT_APPLYOVERALTPAL)) - hictinting_apply(glcolors[i], palnum); - } - else if (tintflags & (HICTINT_USEONART|HICTINT_ALWAYSUSEART)) - hictinting_apply(glcolors[i], palnum); - } - - // global tinting - if ((pth->flags & PTH_HIGHTILE) && have_basepal_tint()) - hictinting_apply(glcolors[i], MAXPALOOKUPS-1); - - globaltinting_apply(glcolors[i]); - } - - i++; - } - - i = 0; - j = 8; // In Polymer, an ART sky has always 8 sides... - while (i < j) - { - GLint oldswrap; - // ... but in case a multi-psky specifies less than 8, repeat cyclically: - const int8_t tileofs = dapskyoff[i&numskytilesm1]; - - glColor4f(glcolors[tileofs][0], glcolors[tileofs][1], glcolors[tileofs][2], 1.0f); - glBindTexture(GL_TEXTURE_2D, glpics[tileofs]); - - glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, &oldswrap); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP); - - polymer_drawartskyquad(i, (i + 1) & (j - 1), height); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, oldswrap); - - i++; - } -} - -static void polymer_drawartskyquad(int32_t p1, int32_t p2, GLfloat height) -{ - glBegin(GL_QUADS); - glTexCoord2f(0.0f, 0.0f); - //OSD_Printf("PR: drawing %f %f %f\n", skybox[(p1 * 2) + 1], height, skybox[p1 * 2]); - glVertex3f(artskydata[(p1 * 2) + 1], height, artskydata[p1 * 2]); - glTexCoord2f(0.0f, 1.0f); - //OSD_Printf("PR: drawing %f %f %f\n", skybox[(p1 * 2) + 1], -height, skybox[p1 * 2]); - glVertex3f(artskydata[(p1 * 2) + 1], -height, artskydata[p1 * 2]); - glTexCoord2f(1.0f, 1.0f); - //OSD_Printf("PR: drawing %f %f %f\n", skybox[(p2 * 2) + 1], -height, skybox[p2 * 2]); - glVertex3f(artskydata[(p2 * 2) + 1], -height, artskydata[p2 * 2]); - glTexCoord2f(1.0f, 0.0f); - //OSD_Printf("PR: drawing %f %f %f\n", skybox[(p2 * 2) + 1], height, skybox[p2 * 2]); - glVertex3f(artskydata[(p2 * 2) + 1], height, artskydata[p2 * 2]); - glEnd(); -} - -static void polymer_drawskybox(int16_t tilenum, char palnum, int8_t shade) -{ - pthtyp* pth; - int32_t i; - GLfloat color[3]; - - if ((pr_vbos > 0) && (skyboxdatavbo == 0)) - { - glGenBuffers(1, &skyboxdatavbo); - - glBindBuffer(GL_ARRAY_BUFFER, skyboxdatavbo); - glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(GLfloat) * 5 * 6, skyboxdata, modelvbousage); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - - if (pr_vbos > 0) - glBindBuffer(GL_ARRAY_BUFFER, skyboxdatavbo); - - DO_TILE_ANIM(tilenum, 0); - - i = 0; - while (i < 6) - { - drawingskybox = i + 1; - pth = texcache_fetch(tilenum, palnum, 0, DAMETH_CLAMPED); - - color[0] = color[1] = color[2] = getshadefactor(shade); - - if (pth) - { - // tinting - polytintflags_t const tintflags = hictinting[palnum].f; - if (!(tintflags & HICTINT_PRECOMPUTED)) - { - if (pth->flags & PTH_HIGHTILE) - { - if (pth->palnum != palnum || (pth->effects & HICTINT_IN_MEMORY) || (tintflags & HICTINT_APPLYOVERALTPAL)) - hictinting_apply(color, palnum); - } - else if (tintflags & (HICTINT_USEONART|HICTINT_ALWAYSUSEART)) - hictinting_apply(color, palnum); - } - - // global tinting - if ((pth->flags & PTH_HIGHTILE) && have_basepal_tint()) - hictinting_apply(color, MAXPALOOKUPS-1); - - globaltinting_apply(color); - } - - glColor4f(color[0], color[1], color[2], 1.0); - glBindTexture(GL_TEXTURE_2D, pth ? pth->glpic : 0); - if (pr_vbos > 0) - { - glVertexPointer(3, GL_FLOAT, 5 * sizeof(GLfloat), (GLfloat*)(4 * 5 * i * sizeof(GLfloat))); - glTexCoordPointer(2, GL_FLOAT, 5 * sizeof(GLfloat), (GLfloat*)(((4 * 5 * i) + 3) * sizeof(GLfloat))); - } else { - glVertexPointer(3, GL_FLOAT, 5 * sizeof(GLfloat), &skyboxdata[4 * 5 * i]); - glTexCoordPointer(2, GL_FLOAT, 5 * sizeof(GLfloat), &skyboxdata[3 + (4 * 5 * i)]); - } - glDrawArrays(GL_QUADS, 0, 4); - - i++; - } - drawingskybox = 0; - - if (pr_vbos > 0) - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -// MDSPRITES -static void polymer_drawmdsprite(uspritetype *tspr) -{ - md3model_t* m; - mdskinmap_t* sk; - float *v0, *v1; - md3surf_t *s; - char targetpal, usinghighpal, foundpalskin; - float spos2[3], spos[3], tspos[3], lpos[3], tlpos[3], vec[3], mat[4][4]; - float ang; - float scale; - double det; - int32_t surfi, i, j; - GLubyte* color; - int32_t materialbits; - float sradius, lradius; - int16_t modellights[PR_MAXLIGHTS]; - char modellightcount; - uint8_t curpriority; - - uint8_t lpal = (tspr->owner >= MAXSPRITES) ? tspr->pal : sprite[tspr->owner].pal; - - m = (md3model_t*)models[tile2model[Ptile2tile(tspr->picnum,lpal)].modelid]; - updateanimation((md2model_t *)m,tspr,lpal); - - if ((pr_vbos > 1) && (m->indices == NULL)) - polymer_loadmodelvbos(m); - - // Hackish, but that means it's a model drawn by rotatesprite. - if (tspriteptr[maxspritesonscreen] == tspr) { - float x, y, z; - - spos[0] = fglobalposy; - spos[1] = fglobalposz * (-1.f/16.f); - spos[2] = -fglobalposx; - - // The coordinates are actually floats disguised as int in this case - memcpy(&x, &tspr->x, sizeof(float)); - memcpy(&y, &tspr->y, sizeof(float)); - memcpy(&z, &tspr->z, sizeof(float)); - - spos2[0] = y - globalposy; - spos2[1] = (z - fglobalposz) * (-1.f/16.f); - spos2[2] = fglobalposx - x; - } else { - spos[0] = (float)tspr->y; - spos[1] = -(float)(tspr->z) / 16.0f; - spos[2] = -(float)tspr->x; - - spos2[0] = spos2[1] = spos2[2] = 0.0f; - } - - ang = (float)((tspr->ang+spriteext[tspr->owner].angoff) & 2047) * (360.f/2048.f); - ang -= 90.0f; - if (((tspr->cstat>>4) & 3) == 2) - ang -= 90.0f; - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - scale = (1.0/4.0); - scale *= m->scale; - if (pr_overridemodelscale) { - scale *= pr_overridemodelscale; - } else { - scale *= m->bscale; - } - - if (tspriteptr[maxspritesonscreen] == tspr) { - float playerang, radplayerang, cosminusradplayerang, sinminusradplayerang, hudzoom; - - playerang = (globalang & 2047) * (360.f/2048.f) - 90.0f; - radplayerang = (globalang & 2047) * (2.0f * fPI / 2048.0f); - cosminusradplayerang = cos(-radplayerang); - sinminusradplayerang = sin(-radplayerang); - hudzoom = 65536.0 / spriteext[tspr->owner].offset.z; - - glTranslatef(spos[0], spos[1], spos[2]); - glRotatef(horizang, -cosminusradplayerang, 0.0f, sinminusradplayerang); - glRotatef(spriteext[tspr->owner].roll * (360.f/2048.f), sinminusradplayerang, 0.0f, cosminusradplayerang); - glRotatef(-playerang, 0.0f, 1.0f, 0.0f); - glScalef(hudzoom, 1.0f, 1.0f); - glRotatef(playerang, 0.0f, 1.0f, 0.0f); - glTranslatef(spos2[0], spos2[1], spos2[2]); - glRotatef(-ang, 0.0f, 1.0f, 0.0f); - } else { - glTranslatef(spos[0], spos[1], spos[2]); - glRotatef(-ang, 0.0f, 1.0f, 0.0f); - } - if (((tspr->cstat>>4) & 3) == 2) - { - glTranslatef(0.0f, 0.0, -(float)(tilesiz[tspr->picnum].y * tspr->yrepeat) / 8.0f); - glRotatef(90.0f, 0.0f, 0.0f, 1.0f); - } - else - glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); - - if ((tspr->cstat & 128) && (((tspr->cstat>>4) & 3) != 2)) - glTranslatef(0.0f, 0.0, -(float)(tilesiz[tspr->picnum].y * tspr->yrepeat) / 8.0f); - - // yoffset differs from zadd in that it does not follow cstat&8 y-flipping - glTranslatef(0.0f, 0.0, m->yoffset * 64 * scale * tspr->yrepeat); - - if (tspr->cstat & 8) - { - glTranslatef(0.0f, 0.0, (float)(tilesiz[tspr->picnum].y * tspr->yrepeat) / 4.0f); - glScalef(1.0f, 1.0f, -1.0f); - } - - if (tspr->cstat & 4) - glScalef(1.0f, -1.0f, 1.0f); - - if (!(tspr->cstat & 4) != !(tspr->cstat & 8)) { - // Only inverting one coordinate will reverse the winding order of - // faces, so we need to account for that when culling. - SWITCH_CULL_DIRECTION; - } - - glScalef(scale * tspr->xrepeat, scale * tspr->xrepeat, scale * tspr->yrepeat); - glTranslatef(0.0f, 0.0, m->zadd * 64); - - // scripted model rotation - if (tspr->owner < MAXSPRITES && - (spriteext[tspr->owner].pitch || spriteext[tspr->owner].roll)) - { - float pitchang, rollang, offsets[3]; - - pitchang = (float)(spriteext[tspr->owner].pitch) * (360.f/2048.f); - rollang = (float)(spriteext[tspr->owner].roll) * (360.f/2048.f); - - offsets[0] = -spriteext[tspr->owner].offset.x / (scale * tspr->xrepeat); - offsets[1] = -spriteext[tspr->owner].offset.y / (scale * tspr->xrepeat); - offsets[2] = (float)(spriteext[tspr->owner].offset.z) / 16.0f / (scale * tspr->yrepeat); - - glTranslatef(-offsets[0], -offsets[1], -offsets[2]); - - glRotatef(pitchang, 0.0f, 1.0f, 0.0f); - glRotatef(rollang, -1.0f, 0.0f, 0.0f); - - glTranslatef(offsets[0], offsets[1], offsets[2]); - } - - glGetFloatv(GL_MODELVIEW_MATRIX, spritemodelview); - - glPopMatrix(); - glPushMatrix(); - glMultMatrixf(spritemodelview); - - // invert this matrix to get the polymer -> mdsprite space - memcpy(mat, spritemodelview, sizeof(float) * 16); - INVERT_4X4(mdspritespace, det, mat); - - // debug code for drawing the model bounding sphere -// glDisable(GL_TEXTURE_2D); -// glBegin(GL_LINES); -// glColor4f(1.0, 0.0, 0.0, 1.0); -// glVertex3f(m->head.frames[m->cframe].cen.x, -// m->head.frames[m->cframe].cen.y, -// m->head.frames[m->cframe].cen.z); -// glVertex3f(m->head.frames[m->cframe].cen.x + m->head.frames[m->cframe].r, -// m->head.frames[m->cframe].cen.y, -// m->head.frames[m->cframe].cen.z); -// glColor4f(0.0, 1.0, 0.0, 1.0); -// glVertex3f(m->head.frames[m->cframe].cen.x, -// m->head.frames[m->cframe].cen.y, -// m->head.frames[m->cframe].cen.z); -// glVertex3f(m->head.frames[m->cframe].cen.x, -// m->head.frames[m->cframe].cen.y + m->head.frames[m->cframe].r, -// m->head.frames[m->cframe].cen.z); -// glColor4f(0.0, 0.0, 1.0, 1.0); -// glVertex3f(m->head.frames[m->cframe].cen.x, -// m->head.frames[m->cframe].cen.y, -// m->head.frames[m->cframe].cen.z); -// glVertex3f(m->head.frames[m->cframe].cen.x, -// m->head.frames[m->cframe].cen.y, -// m->head.frames[m->cframe].cen.z + m->head.frames[m->cframe].r); -// glEnd(); -// glEnable(GL_TEXTURE_2D); - - polymer_getscratchmaterial(&mdspritematerial); - - color = mdspritematerial.diffusemodulation; - - color[0] = color[1] = color[2] = - (GLubyte)(((float)(numshades-min(max((tspr->shade * shadescale)+m->shadeoff,0.f),(float)numshades)))/((float)numshades) * 0xFF); - - usinghighpal = (pr_highpalookups && - prhighpalookups[curbasepal][tspr->pal].map); - - // tinting - polytintflags_t const tintflags = hictinting[tspr->pal].f; - if (!usinghighpal && !(tintflags & HICTINT_PRECOMPUTED)) - { - if (!(m->flags&1)) - hictinting_apply_ub(color, tspr->pal); - else globalnoeffect=1; //mdloadskin reads this - } - - // global tinting - if (!usinghighpal && have_basepal_tint()) - hictinting_apply_ub(color, MAXPALOOKUPS-1); - - globaltinting_apply_ub(color); - - if (tspr->cstat & 2) - { - if (!(tspr->cstat&512)) - color[3] = 0xAA; - else - color[3] = 0x55; - } else - color[3] = 0xFF; - - { - double f = color[3] * (1.0f - spriteext[tspr->owner].alpha); - color[3] = (GLubyte)f; - } - - if (searchit == 2) - { - color[0] = 0x03; - color[1] = ((GLubyte *)(&tspr->owner))[0]; - color[2] = ((GLubyte *)(&tspr->owner))[1]; - color[3] = 0xFF; - } - - if (pr_gpusmoothing) - mdspritematerial.frameprogress = m->interpol; - - mdspritematerial.mdspritespace = GL_TRUE; - - modellightcount = 0; - curpriority = 0; - - // light culling - if (lightcount && (!depth || mirrors[depth-1].plane)) - { - sradius = (m->head.frames[m->cframe].r * (1 - m->interpol)) + - (m->head.frames[m->nframe].r * m->interpol); - - sradius *= max(scale * tspr->xrepeat, scale * tspr->yrepeat); - sradius /= 1000.0f; - - spos[0] = (m->head.frames[m->cframe].cen.x * (1 - m->interpol)) + - (m->head.frames[m->nframe].cen.x * m->interpol); - spos[1] = (m->head.frames[m->cframe].cen.y * (1 - m->interpol)) + - (m->head.frames[m->nframe].cen.y * m->interpol); - spos[2] = (m->head.frames[m->cframe].cen.z * (1 - m->interpol)) + - (m->head.frames[m->nframe].cen.z * m->interpol); - - polymer_transformpoint(spos, tspos, spritemodelview); - polymer_transformpoint(tspos, spos, rootmodelviewmatrix); - - while (curpriority < pr_maxlightpriority) - { - i = j = 0; - while (j < lightcount) - { - while (!prlights[i].flags.active) - i++; - - if (prlights[i].priority != curpriority) - { - i++; - j++; - continue; - } - - lradius = prlights[i].range / 1000.0f; - - lpos[0] = (float)prlights[i].y; - lpos[1] = -(float)prlights[i].z / 16.0f; - lpos[2] = -(float)prlights[i].x; - - polymer_transformpoint(lpos, tlpos, rootmodelviewmatrix); - - vec[0] = tlpos[0] - spos[0]; - vec[0] *= vec[0]; - vec[1] = tlpos[1] - spos[1]; - vec[1] *= vec[1]; - vec[2] = tlpos[2] - spos[2]; - vec[2] *= vec[2]; - - if ((vec[0] + vec[1] + vec[2]) <= ((sradius+lradius) * (sradius+lradius))) - modellights[modellightcount++] = i; - - i++; - j++; - } - curpriority++; - } - } - - for (surfi=0;surfihead.numsurfs;surfi++) - { - s = &m->head.surfs[surfi]; - v0 = &s->geometry[m->cframe*s->numverts*15]; - v1 = &s->geometry[m->nframe*s->numverts*15]; - - // debug code for drawing model normals -// glDisable(GL_TEXTURE_2D); -// glBegin(GL_LINES); -// glColor4f(1.0, 1.0, 1.0, 1.0); -// -// int i = 0; -// while (i < s->numverts) -// { -// glVertex3f(v0[(i * 6) + 0], -// v0[(i * 6) + 1], -// v0[(i * 6) + 2]); -// glVertex3f(v0[(i * 6) + 0] + v0[(i * 6) + 3] * 100, -// v0[(i * 6) + 1] + v0[(i * 6) + 4] * 100, -// v0[(i * 6) + 2] + v0[(i * 6) + 5] * 100); -// i++; -// } -// glEnd(); -// glEnable(GL_TEXTURE_2D); - - - targetpal = tspr->pal; - foundpalskin = 0; - - for (sk = m->skinmap; sk; sk = sk->next) - if ((int32_t)sk->palette == tspr->pal && - sk->skinnum == tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum && - sk->surfnum == surfi) - { - if (sk->specpower != 1.0) - mdspritematerial.specmaterial[0] = sk->specpower; - mdspritematerial.specmaterial[1] = sk->specfactor; - foundpalskin = 1; - } - - // If we have a global palette tint, the palskin won't do us any good - if (curbasepal) - foundpalskin = 0; - - if (!foundpalskin && usinghighpal) { - // We don't have a specific skin defined for this palette - // Use the base skin instead and plug in our highpalookup map - targetpal = 0; - mdspritematerial.highpalookupmap = prhighpalookups[curbasepal][tspr->pal].map; - } - - mdspritematerial.diffusemap = - mdloadskin((md2model_t *)m,tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum,targetpal,surfi); - if (!mdspritematerial.diffusemap) - continue; - - if (!(tspr->extra&TSPR_EXTRA_MDHACK)) - { - mdspritematerial.detailmap = - mdloadskin((md2model_t *)m,tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum,DETAILPAL,surfi); - - for (sk = m->skinmap; sk; sk = sk->next) - if ((int32_t)sk->palette == DETAILPAL && - sk->skinnum == tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum && - sk->surfnum == surfi) - mdspritematerial.detailscale[0] = mdspritematerial.detailscale[1] = sk->param; - - mdspritematerial.specmap = - mdloadskin((md2model_t *)m,tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum,SPECULARPAL,surfi); - - mdspritematerial.normalmap = - mdloadskin((md2model_t *)m,tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum,NORMALPAL,surfi); - - for (sk = m->skinmap; sk; sk = sk->next) - if ((int32_t)sk->palette == NORMALPAL && - sk->skinnum == tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum && - sk->surfnum == surfi) { - mdspritematerial.normalbias[0] = sk->specpower; - mdspritematerial.normalbias[1] = sk->specfactor; - } - - mdspritematerial.glowmap = - mdloadskin((md2model_t *)m,tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum,GLOWPAL,surfi); - } - - glEnableClientState(GL_NORMAL_ARRAY); - - if (pr_vbos > 1) - { - glBindBuffer(GL_ARRAY_BUFFER, m->texcoords[surfi]); - glTexCoordPointer(2, GL_FLOAT, 0, 0); - - glBindBuffer(GL_ARRAY_BUFFER, m->geometry[surfi]); - glVertexPointer(3, GL_FLOAT, sizeof(float) * 15, (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 15)); - glNormalPointer(GL_FLOAT, sizeof(float) * 15, (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 15) + 3); - - mdspritematerial.tbn = (GLfloat*)(m->cframe * s->numverts * sizeof(float) * 15) + 6; - - if (pr_gpusmoothing) { - mdspritematerial.nextframedata = (GLfloat*)(m->nframe * s->numverts * sizeof(float) * 15); - } - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->indices[surfi]); - - curlight = 0; - do { - materialbits = polymer_bindmaterial(&mdspritematerial, modellights, modellightcount); - glDrawElements(GL_TRIANGLES, s->numtris * 3, GL_UNSIGNED_INT, 0); - polymer_unbindmaterial(materialbits); - } while ((++curlight < modellightcount) && (curlight < pr_maxlightpasses)); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - else - { - glVertexPointer(3, GL_FLOAT, sizeof(float) * 15, v0); - glNormalPointer(GL_FLOAT, sizeof(float) * 15, v0 + 3); - glTexCoordPointer(2, GL_FLOAT, 0, s->uv); - - mdspritematerial.tbn = v0 + 6; - - if (pr_gpusmoothing) { - mdspritematerial.nextframedata = (GLfloat*)(v1); - } - - curlight = 0; - do { - materialbits = polymer_bindmaterial(&mdspritematerial, modellights, modellightcount); - glDrawElements(GL_TRIANGLES, s->numtris * 3, GL_UNSIGNED_INT, s->tris); - polymer_unbindmaterial(materialbits); - } while ((++curlight < modellightcount) && (curlight < pr_maxlightpasses)); - } - - glDisableClientState(GL_NORMAL_ARRAY); - } - - glPopMatrix(); - - if (!(tspr->cstat & 4) != !(tspr->cstat & 8)) { - SWITCH_CULL_DIRECTION; - } - - globalnoeffect = 0; -} - -static void polymer_loadmodelvbos(md3model_t* m) -{ - int32_t i; - md3surf_t *s; - - m->indices = (GLuint *)Xmalloc(m->head.numsurfs * sizeof(GLuint)); - m->texcoords = (GLuint *)Xmalloc(m->head.numsurfs * sizeof(GLuint)); - m->geometry = (GLuint *)Xmalloc(m->head.numsurfs * sizeof(GLuint)); - - glGenBuffers(m->head.numsurfs, m->indices); - glGenBuffers(m->head.numsurfs, m->texcoords); - glGenBuffers(m->head.numsurfs, m->geometry); - - i = 0; - while (i < m->head.numsurfs) - { - s = &m->head.surfs[i]; - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->indices[i]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, s->numtris * sizeof(md3tri_t), s->tris, modelvbousage); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - glBindBuffer(GL_ARRAY_BUFFER, m->texcoords[i]); - glBufferData(GL_ARRAY_BUFFER, s->numverts * sizeof(md3uv_t), s->uv, modelvbousage); - - glBindBuffer(GL_ARRAY_BUFFER, m->geometry[i]); - glBufferData(GL_ARRAY_BUFFER, s->numframes * s->numverts * sizeof(float) * (15), s->geometry, modelvbousage); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - i++; - } -} - -// MATERIALS -static void polymer_getscratchmaterial(_prmaterial* material) -{ - // this function returns a material that won't validate any bits - // make sure to keep it up to date with the validation logic in bindmaterial - - // PR_BIT_ANIM_INTERPOLATION - material->frameprogress = 0.0f; - material->nextframedata = (float*)-1; - // PR_BIT_NORMAL_MAP - material->normalmap = 0; - material->normalbias[0] = material->normalbias[1] = 0.0f; - material->tbn = NULL; - // PR_BIT_ART_MAP - material->artmap = 0; - material->basepalmap = 0; - material->lookupmap = 0; - // PR_BIT_DIFFUSE_MAP - material->diffusemap = 0; - material->diffusescale[0] = material->diffusescale[1] = 1.0f; - // PR_BIT_HIGHPALOOKUP_MAP - material->highpalookupmap = 0; - // PR_BIT_DIFFUSE_DETAIL_MAP - material->detailmap = 0; - material->detailscale[0] = material->detailscale[1] = 1.0f; - // PR_BIT_DIFFUSE_MODULATION - material->diffusemodulation[0] = - material->diffusemodulation[1] = - material->diffusemodulation[2] = - material->diffusemodulation[3] = 0xFF; - // PR_BIT_SPECULAR_MAP - material->specmap = 0; - // PR_BIT_SPECULAR_MATERIAL - material->specmaterial[0] = 15.0f; - material->specmaterial[1] = 1.0f; - // PR_BIT_MIRROR_MAP - material->mirrormap = 0; - // PR_BIT_GLOW_MAP - material->glowmap = 0; - // PR_BIT_PROJECTION_MAP - material->mdspritespace = GL_FALSE; -} - -static void polymer_setupartmap(int16_t tilenum, char pal) -{ - if (!prartmaps[tilenum]) { - char *tilebuffer = (char *) waloff[tilenum]; - char *tempbuffer = (char *) Xmalloc(tilesiz[tilenum].x * tilesiz[tilenum].y); - int i, j, k; - - i = k = 0; - while (i < tilesiz[tilenum].y) { - j = 0; - while (j < tilesiz[tilenum].x) { - tempbuffer[k] = tilebuffer[(j * tilesiz[tilenum].y) + i]; - k++; - j++; - } - i++; - } - - glGenTextures(1, &prartmaps[tilenum]); - glBindTexture(GL_TEXTURE_2D, prartmaps[tilenum]); - glTexImage2D(GL_TEXTURE_2D, - 0, - GL_RED, - tilesiz[tilenum].x, - tilesiz[tilenum].y, - 0, - GL_RED, - GL_UNSIGNED_BYTE, - tempbuffer); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glBindTexture(GL_TEXTURE_2D, 0); - Bfree(tempbuffer); - } - - if (!prbasepalmaps[curbasepal]) { - glGenTextures(1, &prbasepalmaps[curbasepal]); - glBindTexture(GL_TEXTURE_2D, prbasepalmaps[curbasepal]); - glTexImage2D(GL_TEXTURE_2D, - 0, - GL_RGB, - 256, - 1, - 0, - GL_RGB, - GL_UNSIGNED_BYTE, - basepaltable[curbasepal]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP); - glBindTexture(GL_TEXTURE_2D, 0); - } - - if (!prlookups[pal]) { - glGenTextures(1, &prlookups[pal]); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, prlookups[pal]); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, - 0, - GL_RED, - 256, - numshades, - 0, - GL_RED, - GL_UNSIGNED_BYTE, - palookup[pal]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - } -} - -static _prbucket* polymer_getbuildmaterial(_prmaterial* material, int16_t tilenum, char pal, int8_t shade, int8_t vis, int32_t cmeth) -{ - // find corresponding bucket; XXX key that with pr_buckets later, need to be tied to restartvid - _prbucket *bucketptr = polymer_findbucket(tilenum, pal); - - polymer_getscratchmaterial(material); - - if (!waloff[tilenum]) - tileLoad(tilenum); - - // PR_BIT_DIFFUSE_MAP - pthtyp *pth = texcache_fetch(tilenum, pal, 0, cmeth); - - if (pth) - { - material->diffusemap = pth->glpic; - - if (pth->hicr) - { - material->diffusescale[0] = pth->hicr->scale.x; - material->diffusescale[1] = pth->hicr->scale.y; - } - } - - int32_t usinghighpal = 0; - - // Lazily fill in all the textures we need, move this to precaching later - if (pr_artmapping && !(globalflags & GLOBAL_NO_GL_TILESHADES) && polymer_eligible_for_artmap(tilenum, pth)) - { - polytintflags_t const tintflags = hictinting[pal].f; - - if (tintflags & (HICTINT_USEONART|HICTINT_ALWAYSUSEART)) - { - if (!(tintflags & HICTINT_APPLYOVERPALSWAP)) - pal = 0; - } - - if (!prartmaps[tilenum] || !prbasepalmaps[curbasepal] || !prlookups[pal]) - polymer_setupartmap(tilenum, pal); - - material->artmap = prartmaps[tilenum]; - material->basepalmap = prbasepalmaps[curbasepal]; - material->lookupmap = prlookups[pal]; - - if (!material->basepalmap || !material->lookupmap) { - material->artmap = 0; - } - - material->shadeoffset = shade; - material->visibility = (uint8_t)(vis+16); - - globaltinting_apply_ub(material->diffusemodulation); - // all the stuff below is mutually exclusive with artmapping - goto done; - } - - // PR_BIT_HIGHPALOOKUP_MAP - if (pr_highpalookups && prhighpalookups[curbasepal][pal].map && - hicfindsubst(tilenum, 0) && - (curbasepal || (hicfindsubst(tilenum, pal)->palnum != pal))) - { - material->highpalookupmap = prhighpalookups[curbasepal][pal].map; - pal = 0; - usinghighpal = 1; - } - - if (pth) - { - if (pth->hicr) - { - // PR_BIT_SPECULAR_MATERIAL - if (pth->hicr->specpower != 1.0f) - material->specmaterial[0] = pth->hicr->specpower; - material->specmaterial[1] = pth->hicr->specfactor; - } - - // PR_BIT_DIFFUSE_MODULATION - material->diffusemodulation[0] = - material->diffusemodulation[1] = - material->diffusemodulation[2] = - (GLubyte)(getshadefactor(shade) * 0xFF); - - // tinting - polytintflags_t const tintflags = hictinting[pal].f; - if (!(tintflags & HICTINT_PRECOMPUTED)) - { - if (pth->flags & PTH_HIGHTILE) - { - if (pth->palnum != pal || (pth->effects & HICTINT_IN_MEMORY) || (tintflags & HICTINT_APPLYOVERALTPAL)) - hictinting_apply_ub(material->diffusemodulation, pal); - } - else if (tintflags & (HICTINT_USEONART|HICTINT_ALWAYSUSEART)) - hictinting_apply_ub(material->diffusemodulation, pal); - } - - // global tinting - if ((pth->flags & PTH_HIGHTILE) && !usinghighpal && have_basepal_tint()) - hictinting_apply_ub(material->diffusemodulation, MAXPALOOKUPS-1); - - globaltinting_apply_ub(material->diffusemodulation); - - // PR_BIT_GLOW_MAP - if (r_fullbrights && pth->flags & PTH_HASFULLBRIGHT) - material->glowmap = pth->ofb->glpic; - } - - // PR_BIT_DIFFUSE_DETAIL_MAP - if (hicfindsubst(tilenum, DETAILPAL, 1) && (pth = texcache_fetch(tilenum, DETAILPAL, 0, DAMETH_NOMASK)) && - pth->hicr && (pth->hicr->palnum == DETAILPAL)) - { - material->detailmap = pth->glpic; - material->detailscale[0] = pth->hicr->scale.x; - material->detailscale[1] = pth->hicr->scale.y; - } - - // PR_BIT_GLOW_MAP - if (hicfindsubst(tilenum, GLOWPAL, 1) && (pth = texcache_fetch(tilenum, GLOWPAL, 0, DAMETH_MASK)) && - pth->hicr && (pth->hicr->palnum == GLOWPAL)) - material->glowmap = pth->glpic; - - // PR_BIT_SPECULAR_MAP - if (hicfindsubst(tilenum, SPECULARPAL, 1) && (pth = texcache_fetch(tilenum, SPECULARPAL, 0, DAMETH_NOMASK)) && - pth->hicr && (pth->hicr->palnum == SPECULARPAL)) - material->specmap = pth->glpic; - - // PR_BIT_NORMAL_MAP - if (hicfindsubst(tilenum, NORMALPAL, 1) && (pth = texcache_fetch(tilenum, NORMALPAL, 0, DAMETH_NOMASK)) && - pth->hicr && (pth->hicr->palnum == NORMALPAL)) - { - material->normalmap = pth->glpic; - material->normalbias[0] = pth->hicr->specpower; - material->normalbias[1] = pth->hicr->specfactor; - } - -done: - if (bucketptr->invalidmaterial != 0) - { - bucketptr->material = *material; - bucketptr->invalidmaterial = 0; - } - - return bucketptr; -} - -static int32_t polymer_bindmaterial(const _prmaterial *material, const int16_t* lights, int matlightcount) -{ - int32_t programbits; - int32_t texunit; - - programbits = 0; - - // --------- bit validation - - // PR_BIT_ANIM_INTERPOLATION - if (material->nextframedata != ((float*)-1)) - programbits |= prprogrambits[PR_BIT_ANIM_INTERPOLATION].bit; - - // PR_BIT_LIGHTING_PASS - if (curlight && matlightcount) - programbits |= prprogrambits[PR_BIT_LIGHTING_PASS].bit; - - // PR_BIT_NORMAL_MAP - if (pr_normalmapping && material->normalmap) - programbits |= prprogrambits[PR_BIT_NORMAL_MAP].bit; - - // PR_BIT_ART_MAP - if (pr_artmapping && material->artmap && - !(globalflags & GLOBAL_NO_GL_TILESHADES) && - (overridematerial & prprogrambits[PR_BIT_ART_MAP].bit)) { - programbits |= prprogrambits[PR_BIT_ART_MAP].bit; - } else - // PR_BIT_DIFFUSE_MAP - if (material->diffusemap) { - programbits |= prprogrambits[PR_BIT_DIFFUSE_MAP].bit; - programbits |= prprogrambits[PR_BIT_DIFFUSE_MAP2].bit; - } - - // PR_BIT_HIGHPALOOKUP_MAP - if (material->highpalookupmap) - programbits |= prprogrambits[PR_BIT_HIGHPALOOKUP_MAP].bit; - - // PR_BIT_DIFFUSE_DETAIL_MAP - if (r_detailmapping && material->detailmap) - programbits |= prprogrambits[PR_BIT_DIFFUSE_DETAIL_MAP].bit; - - // PR_BIT_DIFFUSE_MODULATION - programbits |= prprogrambits[PR_BIT_DIFFUSE_MODULATION].bit; - - // PR_BIT_SPECULAR_MAP - if (pr_specularmapping && material->specmap) - programbits |= prprogrambits[PR_BIT_SPECULAR_MAP].bit; - - // PR_BIT_SPECULAR_MATERIAL - if ((material->specmaterial[0] != 15.0) || (material->specmaterial[1] != 1.0) || pr_overridespecular) - programbits |= prprogrambits[PR_BIT_SPECULAR_MATERIAL].bit; - - // PR_BIT_MIRROR_MAP - if (!curlight && material->mirrormap) - programbits |= prprogrambits[PR_BIT_MIRROR_MAP].bit; - - // PR_BIT_FOG - if (!material->artmap && !curlight && !material->mirrormap) - programbits |= prprogrambits[PR_BIT_FOG].bit; - - // PR_BIT_GLOW_MAP - if (!curlight && r_glowmapping && material->glowmap) - programbits |= prprogrambits[PR_BIT_GLOW_MAP].bit; - - // PR_BIT_POINT_LIGHT - if (matlightcount) { - programbits |= prprogrambits[PR_BIT_POINT_LIGHT].bit; - // PR_BIT_SPOT_LIGHT - if (prlights[lights[curlight]].radius) { - programbits |= prprogrambits[PR_BIT_SPOT_LIGHT].bit; - // PR_BIT_SHADOW_MAP - if (prlights[lights[curlight]].rtindex != -1) { - programbits |= prprogrambits[PR_BIT_SHADOW_MAP].bit; - programbits |= prprogrambits[PR_BIT_PROJECTION_MAP].bit; - } - // PR_BIT_LIGHT_MAP - if (prlights[lights[curlight]].lightmap) { - programbits |= prprogrambits[PR_BIT_LIGHT_MAP].bit; - programbits |= prprogrambits[PR_BIT_PROJECTION_MAP].bit; - } - } - } - - // material override - programbits &= overridematerial; - - programbits |= prprogrambits[PR_BIT_HEADER].bit; - programbits |= prprogrambits[PR_BIT_FOOTER].bit; - - // --------- program compiling - if (!prprograms[programbits].handle) - polymer_compileprogram(programbits); - - useShaderProgram(prprograms[programbits].handle); - - // --------- bit setup - - texunit = 0; - - // PR_BIT_ANIM_INTERPOLATION - if (programbits & prprogrambits[PR_BIT_ANIM_INTERPOLATION].bit) - { - glEnableVertexAttribArray(prprograms[programbits].attrib_nextFrameData); - if (prprograms[programbits].attrib_nextFrameNormal != -1) - glEnableVertexAttribArray(prprograms[programbits].attrib_nextFrameNormal); - glVertexAttribPointer(prprograms[programbits].attrib_nextFrameData, - 3, GL_FLOAT, GL_FALSE, - sizeof(float) * 15, - material->nextframedata); - if (prprograms[programbits].attrib_nextFrameNormal != -1) - glVertexAttribPointer(prprograms[programbits].attrib_nextFrameNormal, - 3, GL_FLOAT, GL_FALSE, - sizeof(float) * 15, - material->nextframedata + 3); - - glUniform1f(prprograms[programbits].uniform_frameProgress, material->frameprogress); - } - - // PR_BIT_LIGHTING_PASS - if (programbits & prprogrambits[PR_BIT_LIGHTING_PASS].bit) - { - glPushAttrib(GL_COLOR_BUFFER_BIT); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); - - if (prlights[lights[curlight]].publicflags.negative) { - glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); - } - } - - // PR_BIT_NORMAL_MAP - if (programbits & prprogrambits[PR_BIT_NORMAL_MAP].bit) - { - float pos[3], bias[2]; - - pos[0] = fglobalposy; - pos[1] = fglobalposz * (-1.f/16.f); - pos[2] = -fglobalposx; - - glActiveTexture(texunit + GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, material->normalmap); - - if (material->mdspritespace == GL_TRUE) { - float mdspritespacepos[3]; - polymer_transformpoint(pos, mdspritespacepos, (float *)mdspritespace); - glUniform3fv(prprograms[programbits].uniform_eyePosition, 1, mdspritespacepos); - } else - glUniform3fv(prprograms[programbits].uniform_eyePosition, 1, pos); - glUniform1i(prprograms[programbits].uniform_normalMap, texunit); - if (pr_overrideparallax) { - bias[0] = pr_parallaxscale; - bias[1] = pr_parallaxbias; - glUniform2fv(prprograms[programbits].uniform_normalBias, 1, bias); - } else - glUniform2fv(prprograms[programbits].uniform_normalBias, 1, material->normalbias); - - if (material->tbn) { - glEnableVertexAttribArray(prprograms[programbits].attrib_T); - glEnableVertexAttribArray(prprograms[programbits].attrib_B); - glEnableVertexAttribArray(prprograms[programbits].attrib_N); - - glVertexAttribPointer(prprograms[programbits].attrib_T, - 3, GL_FLOAT, GL_FALSE, - sizeof(float) * 15, - material->tbn); - glVertexAttribPointer(prprograms[programbits].attrib_B, - 3, GL_FLOAT, GL_FALSE, - sizeof(float) * 15, - material->tbn + 3); - glVertexAttribPointer(prprograms[programbits].attrib_N, - 3, GL_FLOAT, GL_FALSE, - sizeof(float) * 15, - material->tbn + 6); - } - - texunit++; - } - - // PR_BIT_ART_MAP - if (programbits & prprogrambits[PR_BIT_ART_MAP].bit) - { - glActiveTexture(texunit + GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, material->artmap); - - glUniform1i(prprograms[programbits].uniform_artMap, texunit); - - texunit++; - - glActiveTexture(texunit + GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, material->basepalmap); - - glUniform1i(prprograms[programbits].uniform_basePalMap, texunit); - - texunit++; - - glActiveTexture(texunit + GL_TEXTURE0); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, material->lookupmap); - - glUniform1i(prprograms[programbits].uniform_lookupMap, texunit); - - texunit++; - - glUniform1f(prprograms[programbits].uniform_shadeOffset, (GLfloat)material->shadeoffset); - if (r_usenewshading == 4) - { - // the fog in Polymer is a sphere insted of a plane, the furthest visible point should be the same as Polymost - glUniform1f(prprograms[programbits].uniform_visibility, globalvisibility / 262144.f * material->visibility); - } - else - { - static constexpr float material_visibility_divisor = 16.f; - - // NOTE: the denominator was 1.024, but we increase it towards a bit - // farther far clipoff distance to account for the fact that the - // distance to the fragment is the common Euclidean one, as opposed to - // the "ortho" distance of Build. - static constexpr float factor_new = 1.f / ((2048.f * (1.07f / 1.024f) * (150.f / 230.f) / 35.f) * material_visibility_divisor); - - static constexpr float factor_old = 1.f / ((2048.f * (1.07f / 1.024f) / 35.f) * material_visibility_divisor); - - glUniform1f(prprograms[programbits].uniform_visibility, globalvisibility * material->visibility * r_usenewshading > 1 ? factor_new : factor_old); - } - } - - // PR_BIT_DIFFUSE_MAP - if (programbits & prprogrambits[PR_BIT_DIFFUSE_MAP].bit) - { - glActiveTexture(texunit + GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, material->diffusemap); - - glUniform1i(prprograms[programbits].uniform_diffuseMap, texunit); - glUniform2fv(prprograms[programbits].uniform_diffuseScale, 1, material->diffusescale); - - texunit++; - } - - // PR_BIT_HIGHPALOOKUP_MAP - if (programbits & prprogrambits[PR_BIT_HIGHPALOOKUP_MAP].bit) - { - glActiveTexture(texunit + GL_TEXTURE0); - glBindTexture(GL_TEXTURE_3D, material->highpalookupmap); - - glUniform1i(prprograms[programbits].uniform_highPalookupMap, texunit); - - texunit++; - } - - // PR_BIT_DIFFUSE_DETAIL_MAP - if (programbits & prprogrambits[PR_BIT_DIFFUSE_DETAIL_MAP].bit) - { - float scale[2]; - - // scale by the diffuse map scale if we're not doing normal mapping - if (!(programbits & prprogrambits[PR_BIT_NORMAL_MAP].bit)) - { - scale[0] = material->diffusescale[0] * material->detailscale[0]; - scale[1] = material->diffusescale[1] * material->detailscale[1]; - } else { - scale[0] = material->detailscale[0]; - scale[1] = material->detailscale[1]; - } - - glActiveTexture(texunit + GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, material->detailmap); - - glUniform1i(prprograms[programbits].uniform_detailMap, texunit); - glUniform2fv(prprograms[programbits].uniform_detailScale, 1, scale); - - texunit++; - } - - // PR_BIT_DIFFUSE_MODULATION - if (programbits & prprogrambits[PR_BIT_DIFFUSE_MODULATION].bit) - { - glColor4ub(material->diffusemodulation[0], - material->diffusemodulation[1], - material->diffusemodulation[2], - material->diffusemodulation[3]); - } - - // PR_BIT_SPECULAR_MAP - if (programbits & prprogrambits[PR_BIT_SPECULAR_MAP].bit) - { - glActiveTexture(texunit + GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, material->specmap); - - glUniform1i(prprograms[programbits].uniform_specMap, texunit); - - texunit++; - } - - // PR_BIT_SPECULAR_MATERIAL - if (programbits & prprogrambits[PR_BIT_SPECULAR_MATERIAL].bit) - { - float specmaterial[2]; - - if (pr_overridespecular) { - specmaterial[0] = pr_specularpower; - specmaterial[1] = pr_specularfactor; - glUniform2fv(prprograms[programbits].uniform_specMaterial, 1, specmaterial); - } else - glUniform2fv(prprograms[programbits].uniform_specMaterial, 1, material->specmaterial); - } - - // PR_BIT_MIRROR_MAP - if (programbits & prprogrambits[PR_BIT_MIRROR_MAP].bit) - { - glActiveTexture(texunit + GL_TEXTURE0); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, material->mirrormap); - - glUniform1i(prprograms[programbits].uniform_mirrorMap, texunit); - - texunit++; - } -#ifdef PR_LINEAR_FOG - if (programbits & prprogrambits[PR_BIT_FOG].bit) - { - glUniform1i(prprograms[programbits].uniform_linearFog, r_usenewshading >= 2); - } -#endif - // PR_BIT_GLOW_MAP - if (programbits & prprogrambits[PR_BIT_GLOW_MAP].bit) - { - glActiveTexture(texunit + GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, material->glowmap); - - glUniform1i(prprograms[programbits].uniform_glowMap, texunit); - - texunit++; - } - - // PR_BIT_POINT_LIGHT - if (programbits & prprogrambits[PR_BIT_POINT_LIGHT].bit) - { - float inpos[4], pos[4]; - float range[2]; - float color[4]; - - inpos[0] = (float)prlights[lights[curlight]].y; - inpos[1] = -(float)prlights[lights[curlight]].z / 16.0f; - inpos[2] = -(float)prlights[lights[curlight]].x; - - polymer_transformpoint(inpos, pos, curmodelviewmatrix); - - // PR_BIT_SPOT_LIGHT - if (programbits & prprogrambits[PR_BIT_SPOT_LIGHT].bit) - { - float sinang, cosang, sinhorizang, coshorizangs; - float indir[3], dir[3]; - - cosang = (float)(sintable[(-prlights[lights[curlight]].angle+1024)&2047]) / 16383.0f; - sinang = (float)(sintable[(-prlights[lights[curlight]].angle+512)&2047]) / 16383.0f; - coshorizangs = (float)(sintable[(getangle(128, prlights[lights[curlight]].horiz-100)+1024)&2047]) / 16383.0f; - sinhorizang = (float)(sintable[(getangle(128, prlights[lights[curlight]].horiz-100)+512)&2047]) / 16383.0f; - - indir[0] = inpos[0] + sinhorizang * cosang; - indir[1] = inpos[1] - coshorizangs; - indir[2] = inpos[2] - sinhorizang * sinang; - - polymer_transformpoint(indir, dir, curmodelviewmatrix); - - dir[0] -= pos[0]; - dir[1] -= pos[1]; - dir[2] -= pos[2]; - - indir[0] = (float)(sintable[(prlights[lights[curlight]].radius+512)&2047]) / 16383.0f; - indir[1] = (float)(sintable[(prlights[lights[curlight]].faderadius+512)&2047]) / 16383.0f; - indir[1] = 1.0 / (indir[1] - indir[0]); - - glUniform3fv(prprograms[programbits].uniform_spotDir, 1, dir); - glUniform2fv(prprograms[programbits].uniform_spotRadius, 1, indir); - - // PR_BIT_PROJECTION_MAP - if (programbits & prprogrambits[PR_BIT_PROJECTION_MAP].bit) - { - GLfloat matrix[16]; - - glMatrixMode(GL_TEXTURE); - glLoadMatrixf(shadowBias); - glMultMatrixf(prlights[lights[curlight]].proj); - glMultMatrixf(prlights[lights[curlight]].transform); - if (material->mdspritespace == GL_TRUE) - glMultMatrixf(spritemodelview); - glGetFloatv(GL_TEXTURE_MATRIX, matrix); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - - glUniformMatrix4fv(prprograms[programbits].uniform_shadowProjMatrix, 1, GL_FALSE, matrix); - - // PR_BIT_SHADOW_MAP - if (programbits & prprogrambits[PR_BIT_SHADOW_MAP].bit) - { - glActiveTexture(texunit + GL_TEXTURE0); - glBindTexture(prrts[prlights[lights[curlight]].rtindex].target, prrts[prlights[lights[curlight]].rtindex].z); - - glUniform1i(prprograms[programbits].uniform_shadowMap, texunit); - - texunit++; - } - - // PR_BIT_LIGHT_MAP - if (programbits & prprogrambits[PR_BIT_LIGHT_MAP].bit) - { - glActiveTexture(texunit + GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, prlights[lights[curlight]].lightmap); - - glUniform1i(prprograms[programbits].uniform_lightMap, texunit); - - texunit++; - } - } - } - - range[0] = prlights[lights[curlight]].range / 1000.0f; - range[1] = 1 / (range[0] * range[0]); - - color[0] = prlights[lights[curlight]].color[0] / 255.0f; - color[1] = prlights[lights[curlight]].color[1] / 255.0f; - color[2] = prlights[lights[curlight]].color[2] / 255.0f; - - // If this isn't a lighting-only pass, just negate the components - if (!curlight && prlights[lights[curlight]].publicflags.negative) { - color[0] = -color[0]; - color[1] = -color[1]; - color[2] = -color[2]; - } - - glLightfv(GL_LIGHT0, GL_AMBIENT, pos); - glLightfv(GL_LIGHT0, GL_DIFFUSE, color); - if (material->mdspritespace == GL_TRUE) { - float mdspritespacepos[3]; - polymer_transformpoint(inpos, mdspritespacepos, (float *)mdspritespace); - glLightfv(GL_LIGHT0, GL_SPECULAR, mdspritespacepos); - } else { - glLightfv(GL_LIGHT0, GL_SPECULAR, inpos); - } - glLightfv(GL_LIGHT0, GL_LINEAR_ATTENUATION, &range[1]); - } - - glActiveTexture(GL_TEXTURE0); - - return programbits; -} - -static void polymer_unbindmaterial(int32_t programbits) -{ - // repair any dirty GL state here - - // PR_BIT_ANIM_INTERPOLATION - if (programbits & prprogrambits[PR_BIT_ANIM_INTERPOLATION].bit) - { - if (prprograms[programbits].attrib_nextFrameNormal != -1) - glDisableVertexAttribArray(prprograms[programbits].attrib_nextFrameNormal); - glDisableVertexAttribArray(prprograms[programbits].attrib_nextFrameData); - } - - // PR_BIT_LIGHTING_PASS - if (programbits & prprogrambits[PR_BIT_LIGHTING_PASS].bit) - { - glPopAttrib(); - } - - // PR_BIT_NORMAL_MAP - if (programbits & prprogrambits[PR_BIT_NORMAL_MAP].bit) - { - glDisableVertexAttribArray(prprograms[programbits].attrib_T); - glDisableVertexAttribArray(prprograms[programbits].attrib_B); - glDisableVertexAttribArray(prprograms[programbits].attrib_N); - } - - useShaderProgram(0); -} - -static void polymer_compileprogram(int32_t programbits) -{ - int32_t i, enabledbits; - GLuint vert, frag, program; - const GLchar* source[PR_BIT_COUNT * 2]; - GLchar infobuffer[PR_INFO_LOG_BUFFER_SIZE]; - GLint linkstatus; - - // --------- VERTEX - vert = glCreateShader(GL_VERTEX_SHADER); - - enabledbits = i = 0; - while (i < PR_BIT_COUNT) - { - if (programbits & prprogrambits[i].bit) - source[enabledbits++] = prprogrambits[i].vert_def; - i++; - } - i = 0; - while (i < PR_BIT_COUNT) - { - if (programbits & prprogrambits[i].bit) - source[enabledbits++] = prprogrambits[i].vert_prog; - i++; - } - - glShaderSource(vert, enabledbits, source, NULL); - - glCompileShader(vert); - - // --------- FRAGMENT - frag = glCreateShader(GL_FRAGMENT_SHADER); - - enabledbits = i = 0; - while (i < PR_BIT_COUNT) - { - if (programbits & prprogrambits[i].bit) - source[enabledbits++] = prprogrambits[i].frag_def; - i++; - } - i = 0; - while (i < PR_BIT_COUNT) - { - if (programbits & prprogrambits[i].bit) - source[enabledbits++] = prprogrambits[i].frag_prog; - i++; - } - - glShaderSource(frag, enabledbits, (const GLchar**)source, NULL); - - glCompileShader(frag); - - // --------- PROGRAM - program = glCreateProgram(); - - glAttachShader(program, vert); - glAttachShader(program, frag); - - glLinkProgram(program); - - glGetProgramiv(program, GL_LINK_STATUS, &linkstatus); - - glGetProgramInfoLog(program, PR_INFO_LOG_BUFFER_SIZE, NULL, infobuffer); - - prprograms[programbits].handle = program; - -#ifdef DEBUGGINGAIDS - if (pr_verbosity >= 1) -#else - if (pr_verbosity >= 2) -#endif - OSD_Printf("PR : Compiling GPU program with bits (octal) %o...\n", (unsigned)programbits); - if (!linkstatus) { - OSD_Printf("PR : Failed to compile GPU program with bits (octal) %o!\n", (unsigned)programbits); - if (pr_verbosity >= 1) OSD_Printf("PR : Compilation log:\n%s\n", infobuffer); - glGetShaderSource(vert, PR_INFO_LOG_BUFFER_SIZE, NULL, infobuffer); - if (pr_verbosity >= 1) OSD_Printf("PR : Vertex source dump:\n%s\n", infobuffer); - glGetShaderSource(frag, PR_INFO_LOG_BUFFER_SIZE, NULL, infobuffer); - if (pr_verbosity >= 1) OSD_Printf("PR : Fragment source dump:\n%s\n", infobuffer); - } - - // --------- ATTRIBUTE/UNIFORM LOCATIONS - - // PR_BIT_ANIM_INTERPOLATION - if (programbits & prprogrambits[PR_BIT_ANIM_INTERPOLATION].bit) - { - prprograms[programbits].attrib_nextFrameData = glGetAttribLocation(program, "nextFrameData"); - prprograms[programbits].attrib_nextFrameNormal = glGetAttribLocation(program, "nextFrameNormal"); - prprograms[programbits].uniform_frameProgress = glGetUniformLocation(program, "frameProgress"); - } - - // PR_BIT_NORMAL_MAP - if (programbits & prprogrambits[PR_BIT_NORMAL_MAP].bit) - { - prprograms[programbits].attrib_T = glGetAttribLocation(program, "T"); - prprograms[programbits].attrib_B = glGetAttribLocation(program, "B"); - prprograms[programbits].attrib_N = glGetAttribLocation(program, "N"); - prprograms[programbits].uniform_eyePosition = glGetUniformLocation(program, "eyePosition"); - prprograms[programbits].uniform_normalMap = glGetUniformLocation(program, "normalMap"); - prprograms[programbits].uniform_normalBias = glGetUniformLocation(program, "normalBias"); - } - - // PR_BIT_ART_MAP - if (programbits & prprogrambits[PR_BIT_ART_MAP].bit) - { - prprograms[programbits].uniform_artMap = glGetUniformLocation(program, "artMap"); - prprograms[programbits].uniform_basePalMap = glGetUniformLocation(program, "basePalMap"); - prprograms[programbits].uniform_lookupMap = glGetUniformLocation(program, "lookupMap"); - prprograms[programbits].uniform_shadeOffset = glGetUniformLocation(program, "shadeOffset"); - prprograms[programbits].uniform_visibility = glGetUniformLocation(program, "visibility"); - } - - // PR_BIT_DIFFUSE_MAP - if (programbits & prprogrambits[PR_BIT_DIFFUSE_MAP].bit) - { - prprograms[programbits].uniform_diffuseMap = glGetUniformLocation(program, "diffuseMap"); - prprograms[programbits].uniform_diffuseScale = glGetUniformLocation(program, "diffuseScale"); - } - - // PR_BIT_HIGHPALOOKUP_MAP - if (programbits & prprogrambits[PR_BIT_HIGHPALOOKUP_MAP].bit) - { - prprograms[programbits].uniform_highPalookupMap = glGetUniformLocation(program, "highPalookupMap"); - } - - // PR_BIT_DIFFUSE_DETAIL_MAP - if (programbits & prprogrambits[PR_BIT_DIFFUSE_DETAIL_MAP].bit) - { - prprograms[programbits].uniform_detailMap = glGetUniformLocation(program, "detailMap"); - prprograms[programbits].uniform_detailScale = glGetUniformLocation(program, "detailScale"); - } - - // PR_BIT_SPECULAR_MAP - if (programbits & prprogrambits[PR_BIT_SPECULAR_MAP].bit) - { - prprograms[programbits].uniform_specMap = glGetUniformLocation(program, "specMap"); - } - - // PR_BIT_SPECULAR_MATERIAL - if (programbits & prprogrambits[PR_BIT_SPECULAR_MATERIAL].bit) - { - prprograms[programbits].uniform_specMaterial = glGetUniformLocation(program, "specMaterial"); - } - - // PR_BIT_MIRROR_MAP - if (programbits & prprogrambits[PR_BIT_MIRROR_MAP].bit) - { - prprograms[programbits].uniform_mirrorMap = glGetUniformLocation(program, "mirrorMap"); - } -#ifdef PR_LINEAR_FOG - if (programbits & prprogrambits[PR_BIT_FOG].bit) - { - prprograms[programbits].uniform_linearFog = glGetUniformLocation(program, "linearFog"); - } -#endif - // PR_BIT_GLOW_MAP - if (programbits & prprogrambits[PR_BIT_GLOW_MAP].bit) - { - prprograms[programbits].uniform_glowMap = glGetUniformLocation(program, "glowMap"); - } - - // PR_BIT_PROJECTION_MAP - if (programbits & prprogrambits[PR_BIT_PROJECTION_MAP].bit) - { - prprograms[programbits].uniform_shadowProjMatrix = glGetUniformLocation(program, "shadowProjMatrix"); - } - - // PR_BIT_SHADOW_MAP - if (programbits & prprogrambits[PR_BIT_SHADOW_MAP].bit) - { - prprograms[programbits].uniform_shadowMap = glGetUniformLocation(program, "shadowMap"); - } - - // PR_BIT_LIGHT_MAP - if (programbits & prprogrambits[PR_BIT_LIGHT_MAP].bit) - { - prprograms[programbits].uniform_lightMap = glGetUniformLocation(program, "lightMap"); - } - - // PR_BIT_SPOT_LIGHT - if (programbits & prprogrambits[PR_BIT_SPOT_LIGHT].bit) - { - prprograms[programbits].uniform_spotDir = glGetUniformLocation(program, "spotDir"); - prprograms[programbits].uniform_spotRadius = glGetUniformLocation(program, "spotRadius"); - } -} - -// LIGHTS -static void polymer_removelight(int16_t lighti) -{ - _prplanelist* oldhead; - - while (prlights[lighti].planelist) - { - polymer_deleteplanelight(prlights[lighti].planelist->plane, lighti); - oldhead = prlights[lighti].planelist; - prlights[lighti].planelist = prlights[lighti].planelist->n; - oldhead->n = plpool; - plpool = oldhead; - plpool->plane = NULL; - } - prlights[lighti].planecount = 0; - prlights[lighti].planelist = NULL; -} - -static void polymer_updatelights(void) -{ - int32_t i = 0; - - do - { - _prlight* light = &prlights[i]; - - if (light->flags.active && light->flags.invalidate) { - // highly suboptimal - polymer_removelight(i); - - if (light->radius) - polymer_processspotlight(light); - - polymer_culllight(i); - - light->flags.invalidate = 0; - } - - if (light->flags.active) { - // get the texture handle for the lightmap - if (light->radius && light->tilenum > 0) - { - int16_t picnum = light->tilenum; - pthtyp* pth; - - DO_TILE_ANIM(picnum, 0); - - if (!waloff[picnum]) - tileLoad(picnum); - - pth = NULL; - pth = texcache_fetch(picnum, 0, 0, DAMETH_NOMASK); - - if (pth) - light->lightmap = pth->glpic; - } - - light->rtindex = -1; - } - } - while (++i < PR_MAXLIGHTS); -} - -static inline void polymer_resetplanelights(_prplane* plane) -{ - Bmemset(&plane->lights[0], -1, sizeof(plane->lights[0]) * plane->lightcount); - plane->lightcount = 0; -} - -static void polymer_addplanelight(_prplane* plane, int16_t lighti) -{ - _prplanelist* oldhead; - int32_t i = 0; - - if (plane->lightcount) - { - if (plane->lightcount == PR_MAXLIGHTS - 1) - return; - - do - { - if (plane->lights[i++] == lighti) - goto out; - } - while (i < plane->lightcount); - - i = 0; - while (i < plane->lightcount && prlights[plane->lights[i]].priority < prlights[lighti].priority) - i++; - Bmemmove(&plane->lights[i+1], &plane->lights[i], sizeof(int16_t) * (plane->lightcount - i)); - } - - plane->lights[i] = lighti; - plane->lightcount++; - -out: - oldhead = prlights[lighti].planelist; - while (oldhead != NULL) - { - if (oldhead->plane == plane) return; - oldhead = oldhead->n; - } - - oldhead = prlights[lighti].planelist; - if (plpool == NULL) - { - prlights[lighti].planelist = (_prplanelist *) Xmalloc(sizeof(_prplanelist)); - prlights[lighti].planelist->n = oldhead; - } - else - { - prlights[lighti].planelist = plpool; - plpool = plpool->n; - prlights[lighti].planelist->n = oldhead; - } - - prlights[lighti].planelist->plane = plane; - prlights[lighti].planecount++; -} - -static inline void polymer_deleteplanelight(_prplane* plane, int16_t lighti) -{ - int32_t i = plane->lightcount-1; - - while (i >= 0) - { - if (plane->lights[i] == lighti) - { - Bmemmove(&plane->lights[i], &plane->lights[i+1], sizeof(int16_t) * (plane->lightcount - i)); - plane->lightcount--; - return; - } - i--; - } -} - -static int32_t polymer_planeinlight(_prplane* plane, _prlight* light) -{ - float lightpos[3]; - int32_t i, j, k, l; - - if (!plane->vertcount) - return 0; - - if (light->radius) - return polymer_planeinfrustum(plane, light->frustum); - - lightpos[0] = (float)light->y; - lightpos[1] = -(float)light->z / 16.0f; - lightpos[2] = -(float)light->x; - - i = 0; - - do - { - j = k = l = 0; - - do - { - if ((&plane->buffer[j].x)[i] > (lightpos[i] + light->range)) k++; - if ((&plane->buffer[j].x)[i] < (lightpos[i] - light->range)) l++; - } - while (++j < plane->vertcount); - - if ((k == plane->vertcount) || (l == plane->vertcount)) - return 0; - } - while (++i < 3); - - return 1; -} - -static void polymer_invalidateplanelights(_prplane* plane) -{ - int32_t i = plane->lightcount; - - while (i--) - { - if (((unsigned)plane->lights[i] < PR_MAXLIGHTS) && (prlights[plane->lights[i]].flags.active)) - prlights[plane->lights[i]].flags.invalidate = 1; - } -} - -static void polymer_invalidatesectorlights(int16_t sectnum) -{ - int32_t i; - _prsector *s = prsectors[sectnum]; - sectortype *sec = §or[sectnum]; - - if (!s) - return; - - polymer_invalidateplanelights(&s->floor); - polymer_invalidateplanelights(&s->ceil); - - i = sec->wallnum; - - while (i--) - { - _prwall *w; - if (!(w = prwalls[sec->wallptr + i])) continue; - - polymer_invalidateplanelights(&w->wall); - polymer_invalidateplanelights(&w->over); - polymer_invalidateplanelights(&w->mask); - } -} - -static void polymer_processspotlight(_prlight* light) -{ - float radius, ang, horizang, lightpos[3]; - - // hack to avoid lights beams perpendicular to walls - if ((light->horiz <= 100) && (light->horiz > 90)) - light->horiz = 90; - if ((light->horiz > 100) && (light->horiz < 110)) - light->horiz = 110; - - lightpos[0] = (float)light->y; - lightpos[1] = -(float)light->z / 16.0f; - lightpos[2] = -(float)light->x; - - // calculate the spot light transformations and matrices - radius = (float)(light->radius) * (360.f/2048.f); - ang = (float)(light->angle) * (360.f/2048.f); - horizang = (float)(-getangle(128, light->horiz-100)) * (360.f/2048.f); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - bgluPerspective(radius * 2, 1, 0.1f, light->range * (1.f/1000.f)); - glGetFloatv(GL_PROJECTION_MATRIX, light->proj); - glPopMatrix(); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glRotatef(horizang, 1.0f, 0.0f, 0.0f); - glRotatef(ang, 0.0f, 1.0f, 0.0f); - glScalef(1.0f / 1000.0f, 1.0f / 1000.0f, 1.0f / 1000.0f); - glTranslatef(-lightpos[0], -lightpos[1], -lightpos[2]); - glGetFloatv(GL_MODELVIEW_MATRIX, light->transform); - glPopMatrix(); - - polymer_extractfrustum(light->transform, light->proj, light->frustum); - - light->rtindex = -1; - light->lightmap = 0; -} - -static inline void polymer_culllight(int16_t lighti) -{ - _prlight* light = &prlights[lighti]; - int32_t front = 0; - int32_t back = 1; - int32_t i; - int32_t j; - int32_t zdiff; - int32_t checkror; - int16_t bunchnum; - int16_t ns; - _prsector *s; - _prwall *w; - sectortype *sec; - - Bmemset(drawingstate, 0, sizeof(int16_t) * numsectors); - drawingstate[light->sector] = 1; - - sectorqueue[0] = light->sector; - - do - { - s = prsectors[sectorqueue[front]]; - sec = §or[sectorqueue[front]]; - - polymer_pokesector(sectorqueue[front]); - - checkror = FALSE; - - zdiff = light->z - s->floorz; - if (zdiff < 0) - zdiff = -zdiff; - zdiff >>= 4; - - if (!light->radius && !(sec->floorstat & 1)) { - if (zdiff < light->range) { - polymer_addplanelight(&s->floor, lighti); - checkror = TRUE; - } - } else if (polymer_planeinlight(&s->floor, light)) { - polymer_addplanelight(&s->floor, lighti); - checkror = TRUE; - } - -#ifdef YAX_ENABLE - // queue ROR neighbors - if (checkror && - (bunchnum = yax_getbunch(sectorqueue[front], YAX_FLOOR)) >= 0) { - - for (SECTORS_OF_BUNCH(bunchnum, YAX_CEILING, ns)) { - - if (ns >= 0 && !drawingstate[ns] && - polymer_planeinlight(&prsectors[ns]->ceil, light)) { - - sectorqueue[back++] = ns; - drawingstate[ns] = 1; - } - } - } -#endif - checkror = FALSE; - - zdiff = light->z - s->ceilingz; - if (zdiff < 0) - zdiff = -zdiff; - zdiff >>= 4; - - if (!light->radius && !(sec->ceilingstat & 1)) { - if (zdiff < light->range) { - polymer_addplanelight(&s->ceil, lighti); - checkror = TRUE; - } - } else if (polymer_planeinlight(&s->ceil, light)) { - polymer_addplanelight(&s->ceil, lighti); - checkror = TRUE; - } - -#ifdef YAX_ENABLE - // queue ROR neighbors - if (checkror && - (bunchnum = yax_getbunch(sectorqueue[front], YAX_CEILING)) >= 0) { - - for (SECTORS_OF_BUNCH(bunchnum, YAX_FLOOR, ns)) { - - if (ns >= 0 && !drawingstate[ns] && - polymer_planeinlight(&prsectors[ns]->floor, light)) { - - sectorqueue[back++] = ns; - drawingstate[ns] = 1; - } - } - } -#endif - i = 0; - while (i < sec->wallnum) - { - w = prwalls[sec->wallptr + i]; - - j = 0; - - if (polymer_planeinlight(&w->wall, light)) { - polymer_addplanelight(&w->wall, lighti); - j++; - } - - if (polymer_planeinlight(&w->over, light)) { - polymer_addplanelight(&w->over, lighti); - j++; - } - - // assume the light hits the middle section if it hits the top and bottom - if (wallvisible(light->x, light->y, sec->wallptr + i) && - (j == 2 || polymer_planeinlight(&w->mask, light))) { - if ((w->mask.vertcount == 4) && - (w->mask.buffer[0].y >= w->mask.buffer[3].y) && - (w->mask.buffer[1].y >= w->mask.buffer[2].y)) - { - i++; - continue; - } - - polymer_addplanelight(&w->mask, lighti); - - if ((wall[sec->wallptr + i].nextsector >= 0) && - (!drawingstate[wall[sec->wallptr + i].nextsector])) { - drawingstate[wall[sec->wallptr + i].nextsector] = 1; - sectorqueue[back] = wall[sec->wallptr + i].nextsector; - back++; - } - } - - i++; - } - front++; - } - while (front != back); - - i = MAXSPRITES-1; - - do - { - _prsprite *s = prsprites[i]; - - if ((sprite[i].cstat & 48) == 0 || s == NULL || sprite[i].statnum == MAXSTATUS || sprite[i].sectnum == MAXSECTORS) - continue; - - if (polymer_planeinlight(&s->plane, light)) - polymer_addplanelight(&s->plane, lighti); - } - while (i--); -} - -static void polymer_prepareshadows(void) -{ - fix16_t oviewangle, oglobalang; - int32_t i, j, k; - int32_t gx, gy, gz; - int32_t oldoverridematerial; - - // for wallvisible() - gx = globalposx; - gy = globalposy; - gz = globalposz; - // build globals used by drawmasks - oviewangle = viewangle; - oglobalang = qglobalang; - - i = j = k = 0; - - while ((k < lightcount) && (j < pr_shadowcount)) - { - while (!prlights[i].flags.active) - i++; - - if (prlights[i].radius && prlights[i].publicflags.emitshadow && - prlights[i].flags.isinview) - { - prlights[i].flags.isinview = 0; - prlights[i].rtindex = j + 1; - if (pr_verbosity >= 3) OSD_Printf("PR : Drawing shadow %i...\n", i); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prrts[prlights[i].rtindex].fbo); - glPushAttrib(GL_VIEWPORT_BIT); - glViewport(0, 0, prrts[prlights[i].rtindex].xdim, prrts[prlights[i].rtindex].ydim); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadMatrixf(prlights[i].proj); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(prlights[i].transform); - - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(5, SHADOW_DEPTH_OFFSET); - - set_globalpos(prlights[i].x, prlights[i].y, prlights[i].z); - - // build globals used by rotatesprite - viewangle = fix16_from_int(prlights[i].angle); - set_globalang(fix16_from_int(prlights[i].angle)); - - oldoverridematerial = overridematerial; - // smooth model shadows - overridematerial = prprogrambits[PR_BIT_ANIM_INTERPOLATION].bit; - // used by alpha-testing for sprite silhouette - overridematerial |= prprogrambits[PR_BIT_DIFFUSE_MAP].bit; - overridematerial |= prprogrambits[PR_BIT_DIFFUSE_MAP2].bit; - - // to force sprite drawing - mirrors[depth++].plane = NULL; - polymer_displayrooms(prlights[i].sector); - depth--; - - overridematerial = oldoverridematerial; - - glDisable(GL_POLYGON_OFFSET_FILL); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - - glPopAttrib(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - - j++; - } - i++; - k++; - } - - set_globalpos(gx, gy, gz); - - viewangle = oviewangle; - set_globalang(oglobalang); -} - -// RENDER TARGETS -static void polymer_initrendertargets(int32_t count) -{ - int32_t i; - - static int32_t ocount; - - if (count == 0) // uninit - { - if (prrts) - { - for (i=0; i 8192) - tilesheetSize = 8192; -#endif tilesheetHalfTexelSize = { 0.5f/tilesheetSize, 0.5f/tilesheetSize }; vec2_t maxTexDimensions = { tilesheetSize, tilesheetSize }; char allPacked = false; @@ -946,7 +939,7 @@ void polymost_glinit() } for (uint32_t i = 0; i < numTilesheets; ++i) { - glGenTextures(1, tilesheetTexIDs+i); + GetTextureHandle(tilesheetTexIDs+i); glBindTexture(GL_TEXTURE_2D, tilesheetTexIDs[i]); uploadtextureindexed(true, {0, 0}, maxTexDimensions, (intptr_t) NULL); } @@ -1080,8 +1073,8 @@ void polymost_glinit() gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n\ gl_TexCoord[0] = mix(gl_TexCoord[0].xyzw, gl_TexCoord[0].yxzw, u_usePalette);\n\ \n\ - gl_TexCoord[3] = gl_TextureMatrix[3] * gl_MultiTexCoord3;\n\ - gl_TexCoord[4] = gl_TextureMatrix[4] * gl_MultiTexCoord4;\n\ + gl_TexCoord[3] = gl_TextureMatrix[3] * gl_MultiTexCoord0;\n\ + gl_TexCoord[4] = gl_TextureMatrix[4] * gl_MultiTexCoord0;\n\ \n\ gl_FogFragCoord = abs(eyeCoordPosition.z);\n\ //gl_FogFragCoord = clamp((gl_Fog.end-abs(eyeCoordPosition.z))*gl_Fog.scale, c_zero, c_one);\n\ @@ -1644,142 +1637,6 @@ static void fixtransparency(coltype *dapic, vec2_t dasiz, vec2_t dasiz2, int32_t } } -#if defined EDUKE32_GLES -// sorted first in increasing order of size, then in decreasing order of quality -static int32_t const texfmts_rgb_mask[] = { GL_RGB5_A1, GL_RGBA, 0 }; -static int32_t const texfmts_rgb[] = { GL_RGB565, GL_RGB5_A1, GL_RGB, GL_RGBA, 0 }; -static int32_t const texfmts_rgba[] = { GL_RGBA4, GL_RGBA, 0 } ; - -static int32_t texfmt_rgb_mask; -static int32_t texfmt_rgb; -static int32_t texfmt_rgba; - -#if defined EDUKE32_IOS -static int32_t const comprtexfmts_rgb[] = { GL_ETC1_RGB8_OES, 0 }; -static int32_t const comprtexfmts_rgba[] = { 0 }; -static int32_t const comprtexfmts_rgb_mask[] = { 0 }; -#else -static int32_t const comprtexfmts_rgb[] = -{ -#ifdef GL_COMPRESSED_RGB8_ETC2 - GL_COMPRESSED_RGB8_ETC2, -#endif -#ifdef GL_ETC1_RGB8_OES - GL_ETC1_RGB8_OES, -#endif - 0 - }; -// TODO: waiting on etcpak support for ETC2 with alpha -static int32_t const comprtexfmts_rgba[] = { /*GL_COMPRESSED_RGBA8_ETC2_EAC,*/ 0 }; -static int32_t const comprtexfmts_rgb_mask[] = { /*GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,*/ 0 }; -#endif - -static int32_t comprtexfmt_rgb_mask; -static int32_t comprtexfmt_rgb; -static int32_t comprtexfmt_rgba; - -# ifdef __cplusplus -extern "C" { -# endif -extern uint64_t ProcessRGB(uint8_t const *); -extern uint64_t ProcessRGB_ETC2(uint8_t const *); -# ifdef __cplusplus -} -# endif - -typedef uint64_t (*ETCFunction_t)(uint8_t const *); - -static ETCFunction_t Polymost_PickETCFunction(int32_t const comprtexfmt) -{ - switch (comprtexfmt) - { -# ifdef GL_ETC1_RGB8_OES - case GL_ETC1_RGB8_OES: - return ProcessRGB; -# endif - -# ifdef GL_COMPRESSED_RGB8_ETC2 - case GL_COMPRESSED_RGB8_ETC2: - return ProcessRGB_ETC2; -# endif - -# if 0 - case GL_COMPRESSED_RGBA8_ETC2_EAC: - fallthrough__; - case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: - fallthrough__; -# endif - - default: - EDUKE32_UNREACHABLE_SECTION(return NULL); - } -} - -static int Polymost_ConfirmNoGLError(void) -{ - GLenum checkerr, err = GL_NO_ERROR; - while ((checkerr = glGetError()) != GL_NO_ERROR) - err = checkerr; - - return err == GL_NO_ERROR; -} - -static int32_t Polymost_TryDummyTexture(coltype const * const pic, int32_t const * formats) -{ - while (*formats) - { - glTexImage2D(GL_TEXTURE_2D, 0, *formats, 4,4, 0, GL_RGBA, GL_UNSIGNED_BYTE, pic); - - if (Polymost_ConfirmNoGLError()) - return *formats; - - ++formats; - } - - initputs("No texture formats supported?!\n"); - - return 0; -} - -static int32_t Polymost_TryCompressedDummyTexture(coltype const * const pic, int32_t const * formats) -{ - while (*formats) - { - ETCFunction_t func = Polymost_PickETCFunction(*formats); - uint64_t const comprpic = func((uint8_t const *)pic); - jwzgles_glCompressedTexImage2D(GL_TEXTURE_2D, 0, *formats, 4,4, 0, sizeof(uint64_t), &comprpic); - - if (Polymost_ConfirmNoGLError()) - return *formats; - - ++formats; - } - - return 0; -} - -static void Polymost_DetermineTextureFormatSupport(void) -{ - // init dummy texture to trigger possible failure of all compression modes - coltype pic[4*4] = { { 0, 0, 0, 0 } }; - GLuint tex = 0; - - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - - BuildGLErrorCheck(); // XXX: Clear errors. - - texfmt_rgb = Polymost_TryDummyTexture(pic, texfmts_rgb); - texfmt_rgba = Polymost_TryDummyTexture(pic, texfmts_rgba); - texfmt_rgb_mask = Polymost_TryDummyTexture(pic, texfmts_rgb_mask); - - comprtexfmt_rgb = Polymost_TryCompressedDummyTexture(pic, comprtexfmts_rgb); - comprtexfmt_rgba = Polymost_TryCompressedDummyTexture(pic, comprtexfmts_rgba); - comprtexfmt_rgb_mask = Polymost_TryCompressedDummyTexture(pic, comprtexfmts_rgb_mask); - - glDeleteTextures(1, &tex); -} -#endif static void Polymost_SendTexToDriver(int32_t const doalloc, vec2_t const siz, @@ -1792,51 +1649,6 @@ static void Polymost_SendTexToDriver(int32_t const doalloc, #endif int32_t const level) { -#if defined EDUKE32_GLES - if (texcompress_ok && comprtexfmt && (siz.x & 3) == 0 && (siz.y & 3) == 0) - { - size_t const picLength = siz.x * siz.y; - size_t const fourRows = siz.x << 2u; - GLsizei const imageSize = picLength >> 1u; // 4x4 pixels --> 8 bytes - uint8_t * const comprpic = (uint8_t *)Xaligned_alloc(8, imageSize); - - ETCFunction_t func = Polymost_PickETCFunction(comprtexfmt); - - coltype buf[4*4]; - uint64_t * out = (uint64_t *)comprpic; - for (coltype const * row = pic, * const pic_end = pic + picLength; row < pic_end; row += fourRows) - for (coltype const * block = row, * const row_end = row + siz.x; block < row_end; block += 4) - { - buf[0] = block[0]; - buf[1] = block[siz.x]; - buf[2] = block[siz.x*2]; - buf[3] = block[siz.x*3]; - buf[4] = block[1]; - buf[5] = block[siz.x+1]; - buf[6] = block[siz.x*2+1]; - buf[7] = block[siz.x*3+1]; - buf[8] = block[2]; - buf[9] = block[siz.x+2]; - buf[10] = block[siz.x*2+2]; - buf[11] = block[siz.x*3+2]; - buf[12] = block[3]; - buf[13] = block[siz.x+3]; - buf[14] = block[siz.x*2+3]; - buf[15] = block[siz.x*3+3]; - - *out++ = func((uint8_t const *)buf); - } - - if (doalloc & 1) - jwzgles_glCompressedTexImage2D(GL_TEXTURE_2D, level, comprtexfmt, siz.x,siz.y, 0, imageSize, comprpic); - else - jwzgles_glCompressedTexSubImage2D(GL_TEXTURE_2D, level, 0,0, siz.x,siz.y, comprtexfmt, imageSize, comprpic); - - Baligned_free(comprpic); - - return; - } -#endif #if B_BIG_ENDIAN GLenum type = GL_UNSIGNED_INT_8_8_8_8; @@ -1852,140 +1664,25 @@ static void Polymost_SendTexToDriver(int32_t const doalloc, void uploadtexture(int32_t doalloc, vec2_t siz, int32_t texfmt, coltype *pic, vec2_t tsiz, int32_t dameth) { - const int artimmunity = !!(dameth & DAMETH_ARTIMMUNITY); - const int hi = !!(dameth & DAMETH_HI); - const int nodownsize = !!(dameth & DAMETH_NODOWNSIZE) || artimmunity; - const int nomiptransfix = !!(dameth & DAMETH_NOFIX); - const int texcompress_ok = !(dameth & DAMETH_NOTEXCOMPRESS) && (glusetexcompr == 2 || (glusetexcompr && !artimmunity)); + int32_t intexfmt = GL_RGBA8; +#ifdef TIMING + cycle_t clock; -#if !defined EDUKE32_GLES - int32_t intexfmt; - if (texcompress_ok && glinfo.texcompr) - intexfmt = GL_COMPRESSED_RGBA; - else - intexfmt = GL_RGBA8; -#else - const int hasalpha = !!(dameth & (DAMETH_HASALPHA|DAMETH_ONEBITALPHA)); - const int onebitalpha = !!(dameth & DAMETH_ONEBITALPHA); + clock.Reset(); + clock.Clock(); +#endif + Polymost_SendTexToDriver(doalloc, siz, texfmt, pic, + intexfmt, + 0); - int32_t const intexfmt = hasalpha ? (onebitalpha ? texfmt_rgb_mask : texfmt_rgba) : texfmt_rgb; - int32_t const comprtexfmt = hasalpha ? (onebitalpha ? comprtexfmt_rgb_mask : comprtexfmt_rgba) : comprtexfmt_rgb; +#ifdef TIMING + clock.Unclock(); + + static int ttt; + OSD_Printf("%d: texture upload %d x %d took %2.3f ms\n", ttt++, siz.x, siz.y, clock.TimeMS()); #endif - dameth &= ~DAMETH_UPLOADTEXTURE_MASK; - - if (gltexmaxsize <= 0) - { - GLint i = 0; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &i); - if (!i) gltexmaxsize = 6; // 2^6 = 64 == default GL max texture size - else - { - gltexmaxsize = 0; - for (; i>1; i>>=1) gltexmaxsize++; -#ifdef EDUKE32_GLES - while ((1<<(gltexmaxsize-1)) > xdim) - gltexmaxsize--; -#endif - } - } - - gltexmiplevel = max(0, min(gltexmaxsize-1, gltexmiplevel)); - - int miplevel = gltexmiplevel; - - while ((siz.x >> miplevel) > (1 << gltexmaxsize) || (siz.y >> miplevel) > (1 << gltexmaxsize)) - miplevel++; - - if (hi && !nodownsize && r_downsize > miplevel) - miplevel = r_downsize; - - // don't use mipmaps if mipmapping is disabled - //POGO: until the texcacheheader can be updated, generate the mipmaps texcache expects if it's enabled - if (!glusetexcache && - (glfiltermodes[gltexfiltermode].min == GL_NEAREST || - glfiltermodes[gltexfiltermode].min == GL_LINEAR)) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - } - - if (!miplevel) - Polymost_SendTexToDriver(doalloc, siz, texfmt, pic, - intexfmt, -#if defined EDUKE32_GLES - comprtexfmt, - texcompress_ok, -#endif - 0); - - // don't generate mipmaps if we're not going to use them - if (!glusetexcache && - (glfiltermodes[gltexfiltermode].min == GL_NEAREST || - glfiltermodes[gltexfiltermode].min == GL_LINEAR)) - { - return; - } - - vec2_t siz2 = siz; - - for (bssize_t j=1; (siz2.x > 1) || (siz2.y > 1); j++) - { - vec2_t const siz3 = { max(1, siz2.x >> 1), max(1, siz2.y >> 1) }; // this came from the GL_ARB_texture_non_power_of_two spec - //x3 = ((x2+1)>>1); y3 = ((y2+1)>>1); - - for (bssize_t y=0; yr = r; wpptr->g = g; wpptr->b = b; wpptr->a = a; break; - case 2: - wpptr->r = ((r+1)>>1); wpptr->g = ((g+1)>>1); wpptr->b = ((b+1)>>1); wpptr->a = ((a+1)>>1); break; - case 3: - wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); wpptr->a = ((a*85+128)>>8); break; - case 4: - wpptr->r = ((r+2)>>2); wpptr->g = ((g+2)>>2); wpptr->b = ((b+2)>>2); wpptr->a = ((a+2)>>2); break; - default: - EDUKE32_UNREACHABLE_SECTION(break); - } - //if (wpptr->a) wpptr->a = 255; - } - } - - if (!nomiptransfix) - { - vec2_t const tsizzle = { (tsiz.x + (1 << j)-1) >> j, (tsiz.y + (1 << j)-1) >> j }; - - fixtransparency(pic, tsizzle, siz3, dameth); - } - - if (j >= miplevel) - Polymost_SendTexToDriver(doalloc, siz3, texfmt, pic, - intexfmt, -#if defined EDUKE32_GLES - comprtexfmt, - texcompress_ok, -#endif - j - miplevel); - - siz2 = siz3; - } + return; } void uploadtextureindexed(int32_t doalloc, vec2_t offset, vec2_t siz, intptr_t tile) @@ -2031,7 +1728,7 @@ void uploadbasepalette(int32_t basepalnum) char allocateTexture = !paletteTextureIDs[basepalnum]; if (allocateTexture) { - glGenTextures(1, &paletteTextureIDs[basepalnum]); + GetTextureHandle(&paletteTextureIDs[basepalnum]); } glBindTexture(GL_TEXTURE_2D, paletteTextureIDs[basepalnum]); if (allocateTexture) @@ -2066,7 +1763,7 @@ void uploadpalswap(int32_t palookupnum) char allocateTexture = !palswapTextureID; if (allocateTexture) { - glGenTextures(1, &palswapTextureID); + GetTextureHandle(&palswapTextureID); } glBindTexture(GL_TEXTURE_2D, palswapTextureID); if (allocateTexture) @@ -2164,7 +1861,7 @@ static void gloadtile_art_indexed(int32_t dapic, int32_t dameth, pthtyp *pth, in } else if (doalloc) { - glGenTextures(1, (GLuint *)&pth->glpic); + GetTextureHandle((GLuint *)&pth->glpic); } glBindTexture(GL_TEXTURE_2D, pth->glpic); @@ -2363,7 +2060,7 @@ void gloadtile_art(int32_t dapic, int32_t dapal, int32_t tintpalnum, int32_t das } } - if (doalloc) glGenTextures(1,(GLuint *)&pth->glpic); //# of textures (make OpenGL allocate structure) + if (doalloc) GetTextureHandle((GLuint *)&pth->glpic); //# of textures (make OpenGL allocate structure) glBindTexture(GL_TEXTURE_2D, pth->glpic); fixtransparency(pic,tsiz,siz,dameth); @@ -2679,7 +2376,7 @@ int32_t gloadtile_hi(int32_t dapic,int32_t dapalnum, int32_t facen, hicreplctyp hicr->flags |= HICR_ARTIMMUNITY; if ((doalloc&3)==1) - glGenTextures(1, &pth->glpic); //# of textures (make OpenGL allocate structure) + GetTextureHandle(&pth->glpic); //# of textures (make OpenGL allocate structure) glBindTexture(GL_TEXTURE_2D, pth->glpic); fixtransparency(pic,tsiz,siz,dameth); @@ -2775,9 +2472,6 @@ void polymost_setupdetailtexture(const int32_t texunits, const int32_t tex) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - glClientActiveTexture(texunits); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); } void polymost_setupglowtexture(const int32_t texunits, const int32_t tex) @@ -2789,9 +2483,6 @@ void polymost_setupglowtexture(const int32_t texunits, const int32_t tex) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - glClientActiveTexture(texunits); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); } #endif @@ -2815,171 +2506,6 @@ static inline pthtyp *our_texcache_fetch(int32_t dameth) return texcache_fetch(globalpicnum, globalpal, getpalookup((r_usetileshades == 1 && !(globalflags & GLOBAL_NO_GL_TILESHADES)) ? globvis>>3 : 0, globalshade), dameth); } -static void polymost2_drawVBO(GLenum mode, - int32_t vertexBufferID, - int32_t indexBufferID, - const int32_t numElements, - float projectionMatrix[4*4], - float modelViewMatrix[4*4], - int32_t dameth, - float texScale[2], - float texOffset[2], - char cullFaces) -{ - if (dameth == DAMETH_BACKFACECULL || - #ifdef YAX_ENABLE - g_nodraw || - #endif - (uint32_t)globalpicnum >= MAXTILES) - { - return; - } - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - if (cullFaces) - { - glEnable(GL_CULL_FACE); - } - //POGOTODO: this is temporary, the permanent fix is to not allow the transform to affect the windings in the first place in polymost2_drawSprite() - if (cullFaces == 1) - { - glCullFace(GL_BACK); - } - else - { - glCullFace(GL_FRONT); - } - - //POGOTODO: in the future, state changes like binding these buffers can be batched. For now, just switch on every VBO rendered - glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID); - - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - - if (palookup[globalpal] == NULL) - { - globalpal = 0; - } - - //Load texture (globalpicnum) - setgotpic(globalpicnum); - if (!waloff[globalpicnum]) - { - tileLoad(globalpicnum); - } - - pthtyp *pth = our_texcache_fetch(dameth | (r_useindexedcolortextures ? PTH_INDEXED : 0)); - - if (!pth) - { - if (editstatus) - { - Bsprintf(ptempbuf, "pth==NULL! (bad pal?) pic=%d pal=%d", globalpicnum, globalpal); - polymost_printext256(8,8, editorcolors[15],editorcolors[5], ptempbuf, 0); - } - return; - } - - glActiveTexture(GL_TEXTURE1); - //POGO: temporarily swapped out blankTextureID for 0 (as the blank texture has been moved into the dynamic tilesheets) - glBindTexture(GL_TEXTURE_2D, (pth && pth->flags & PTH_HASFULLBRIGHT && r_fullbrights) ? pth->ofb->glpic : 0); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); - - glActiveTexture(GL_TEXTURE0); - polymost_bindPth(pth); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); - - //POGOTODO: handle tinting & shading completely with fragment shader - //POGOTODO: handle fullbright & glow completely with fragment shader - - //POGOTODO: glAlphaFunc is deprecated, move this into the fragment shader - float const al = waloff[globalpicnum] ? alphahackarray[globalpicnum] != 0 ? alphahackarray[globalpicnum] * (1.f/255.f): - (pth && pth->hicr && pth->hicr->alphacut >= 0.f ? pth->hicr->alphacut : 0.f) : 0.f; - glAlphaFunc(GL_GREATER, al); - //POGOTODO: batch this, only apply it to sprites that actually need blending - glEnable(GL_BLEND); - glEnable(GL_ALPHA_TEST); - - handle_blend((dameth & DAMETH_MASKPROPS) > DAMETH_MASK, drawpoly_blend, (dameth & DAMETH_MASKPROPS) == DAMETH_TRANS2); - - useShaderProgram(polymost2BasicShaderProgramID); - - //POGOTODO: batch uniform binding - float tint[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - polytint_t const & polytint = hictinting[globalpal]; - //POGOTODO: full bright pass uses its own globalshade... - tint[0] = (1.f-(polytint.sr*(1.f/255.f)))*getshadefactor(globalshade)+(polytint.sr*(1.f/255.f)); - tint[1] = (1.f-(polytint.sg*(1.f/255.f)))*getshadefactor(globalshade)+(polytint.sg*(1.f/255.f)); - tint[2] = (1.f-(polytint.sb*(1.f/255.f)))*getshadefactor(globalshade)+(polytint.sb*(1.f/255.f)); - - // spriteext full alpha control - float alpha = float_trans(dameth & DAMETH_MASKPROPS, drawpoly_blend) * (1.f - drawpoly_alpha); - - if (pth) - { - // tinting - polytintflags_t const tintflags = hictinting[globalpal].f; - if (!(tintflags & HICTINT_PRECOMPUTED)) - { - if (pth->flags & PTH_HIGHTILE) - { - if (pth->palnum != globalpal || (pth->effects & HICTINT_IN_MEMORY) || (tintflags & HICTINT_APPLYOVERALTPAL)) - hictinting_apply(tint, globalpal); - } - else if (tintflags & (HICTINT_USEONART|HICTINT_ALWAYSUSEART)) - hictinting_apply(tint, globalpal); - } - - // global tinting - if ((pth->flags & PTH_HIGHTILE) && have_basepal_tint()) - hictinting_apply(tint, MAXPALOOKUPS-1); - } - - glUniformMatrix4fv(projMatrixLoc, 1, false, projectionMatrix); - glUniformMatrix4fv(mvMatrixLoc, 1, false, modelViewMatrix); - glUniform1i(texSamplerLoc, 0); - glUniform1i(fullBrightSamplerLoc, 1); - glUniform2fv(texOffsetLoc, 1, texOffset); - glUniform2fv(texScaleLoc, 1, texScale); - glUniform4fv(tintLoc, 1, tint); - glUniform1f(alphaLoc, alpha); - const float fogRange[2] = {fogresult, fogresult2}; - glUniform2fv(fogRangeLoc, 1, fogRange); - glUniform4fv(fogColorLoc, 1, (GLfloat*) &fogcol); - - if (indexBufferID == 0) - { - glDrawArrays(mode, - 0, - numElements); - } - else - { - glDrawElements(mode, - numElements, - GL_UNSIGNED_SHORT, - 0); - } - - glDisableVertexAttribArray(0); - glDisableVertexAttribArray(1); - - //POGOTODO: again, these state changes should be batched in the future, rather than on each VBO rendered - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - glDisable(GL_CULL_FACE); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - //polymost_resetVertexPointers(); -} static void polymost_updatePalette() { @@ -2999,54 +2525,6 @@ static void polymost_updatePalette() } } -static void polymost_lockSubBuffer(uint32_t subBufferIndex) -{ - if (drawpolyVertsSync[subBufferIndex]) - { - glDeleteSync(drawpolyVertsSync[subBufferIndex]); - } - - drawpolyVertsSync[subBufferIndex] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); -} - -static void polymost_waitForSubBuffer(uint32_t subBufferIndex) -{ - if (drawpolyVertsSync[subBufferIndex]) - { - while (true) - { - // we only need to flush if there's a possibility that drawpolyVertsBufferLength is - // so small that we can eat through 3 times the buffer size in a single frame - GLenum waitResult = glClientWaitSync(drawpolyVertsSync[subBufferIndex], GL_SYNC_FLUSH_COMMANDS_BIT, 500000); - if (waitResult == GL_ALREADY_SIGNALED || - waitResult == GL_CONDITION_SATISFIED) - { - return; - } - if (waitResult == GL_WAIT_FAILED) - { - OSD_Printf("polymost_waitForSubBuffer: Wait failed! Error 0x%X. Disabling r_persistentStreamBuffer.\n", glGetError()); - r_persistentStreamBuffer = 0; - videoResetMode(); - if (videoSetGameMode(fullscreen,xres,yres,bpp,upscalefactor)) - { - OSD_Printf("polymost_waitForSubBuffer: Video reset failed. Please ensure r_persistentStreamBuffer = 0 and try restarting the game.\n"); - Bexit(1); - } - return; - } - - static char loggedLongWait = false; - if (waitResult == GL_TIMEOUT_EXPIRED && - !loggedLongWait) - { - OSD_Printf("polymost_waitForSubBuffer(): Had to wait for the drawpoly buffer to become available. For performance, try increasing buffer size with r_drawpolyVertsBufferLength.\n"); - loggedLongWait = true; - } - } - } -} - static void polymost_updaterotmat(void) { if (currentShaderProgramID == polymost1CurrentShaderProgramID) @@ -3501,27 +2979,8 @@ do if (nn < 3) continue; - if (nn+drawpolyVertsOffset > (drawpolyVertsSubBufferIndex+1)*drawpolyVertsBufferLength) - { - if (persistentStreamBuffer) - { - // lock this sub buffer - polymost_lockSubBuffer(drawpolyVertsSubBufferIndex); - drawpolyVertsSubBufferIndex = (drawpolyVertsSubBufferIndex+1)%3; - drawpolyVertsOffset = drawpolyVertsSubBufferIndex*drawpolyVertsBufferLength; - // wait for the next sub buffer to become available before writing to it - // our buffer size should be long enough that no waiting is ever necessary - polymost_waitForSubBuffer(drawpolyVertsSubBufferIndex); - } - else - { - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*5*drawpolyVertsBufferLength, NULL, GL_STREAM_DRAW); - drawpolyVertsOffset = 0; - } - } - vec2f_t const invtsiz2 = { 1.f / tsiz2.x, 1.f / tsiz2.y }; - uint32_t off = persistentStreamBuffer ? drawpolyVertsOffset : 0; + glBegin(GL_TRIANGLE_FAN); for (i = 0; i (drawpolyVertsSubBufferIndex+1)*drawpolyVertsBufferLength) - { - if (persistentStreamBuffer) - { - // lock this sub buffer - polymost_lockSubBuffer(drawpolyVertsSubBufferIndex); - drawpolyVertsSubBufferIndex = (drawpolyVertsSubBufferIndex+1)%3; - drawpolyVertsOffset = drawpolyVertsSubBufferIndex*drawpolyVertsBufferLength; - // wait for the next sub buffer to become available before writing to it - // our buffer size should be long enough that no waiting is ever necessary - polymost_waitForSubBuffer(drawpolyVertsSubBufferIndex); - } - else - { - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*5*drawpolyVertsBufferLength, NULL, GL_STREAM_DRAW); - drawpolyVertsOffset = 0; - } - } - vec2f_t const scale = { 1.f / tsiz2.x * hacksc.x, 1.f / tsiz2.y * hacksc.y }; - uint32_t off = persistentStreamBuffer ? drawpolyVertsOffset : 0; - for (bssize_t i = 0; i < npoints; ++i) + glBegin(GL_TRIANGLE_FAN); + for (bssize_t i = 0; i < npoints; ++i) { float const r = 1.f / dd[i]; + //update texcoords + glTexCoord2f( + uu[i] * r * scale.x, + vv[i] * r * scale.y); + //update verts - drawpolyVerts[(off+i)*5] = (px[i] - ghalfx) * r * grhalfxdown10x; - drawpolyVerts[(off+i)*5+1] = (ghoriz - py[i]) * r * grhalfxdown10; - drawpolyVerts[(off+i)*5+2] = r * (1.f / 1024.f); + glVertex3f( + (px[i] - ghalfx) * r * grhalfxdown10x, + (ghoriz - py[i]) * r * grhalfxdown10, + r * (1.f / 1024.f)); - //update texcoords - drawpolyVerts[(off+i)*5+3] = uu[i] * r * scale.x; - drawpolyVerts[(off+i)*5+4] = vv[i] * r * scale.y; } - - if (!persistentStreamBuffer) - { - glBufferSubData(GL_ARRAY_BUFFER, drawpolyVertsOffset*sizeof(float)*5, npoints*sizeof(float)*5, drawpolyVerts); - } - glDrawArrays(GL_TRIANGLE_FAN, drawpolyVertsOffset, npoints); - drawpolyVertsOffset += npoints; - } + glEnd(); + } #ifdef USE_GLEXT - if (videoGetRenderMode() != REND_POLYMOST) - { - while (texunits > GL_TEXTURE0) - { - glActiveTexture(texunits); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - - glClientActiveTexture(texunits); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, 1.0f); - glDisable(GL_TEXTURE_2D); - - --texunits; - } - } polymost_useDetailMapping(false); polymost_useGlowMapping(false); @@ -6662,398 +6078,9 @@ int32_t polymost_lintersect(int32_t x1, int32_t y1, int32_t x2, int32_t y2, #define TSPR_OFFSET_FACTOR .000008f #define TSPR_OFFSET(tspr) ((TSPR_OFFSET_FACTOR + ((tspr->owner != -1 ? tspr->owner & 63 : 1) * TSPR_OFFSET_FACTOR)) * (float)sepdist(globalposx - tspr->x, globalposy - tspr->y, globalposz - tspr->z) * 0.025f) -void polymost2_drawsprite(int32_t snum) -{ - uspritetype *const tspr = tspriteptr[snum]; - - if (EDUKE32_PREDICT_FALSE(bad_tspr(tspr))) - return; - - const usectortype *sec; - - int32_t spritenum = tspr->owner; - - DO_TILE_ANIM(tspr->picnum, spritenum + 32768); - - globalpicnum = tspr->picnum; - globalshade = tspr->shade; - globalpal = tspr->pal; - globalorientation = tspr->cstat; - globvis = globalvisibility; - - if (sector[tspr->sectnum].visibility != 0) - globvis = mulscale4(globvis, (uint8_t)(sector[tspr->sectnum].visibility + 16)); - - vec2f_t off = { 0.f, 0.f }; - - if ((globalorientation & CSTAT_SPRITE_ALIGNMENT) != CSTAT_SPRITE_ALIGNMENT_SLAB) // only non-voxel sprites should do this - { - int const flag = usehightile && h_xsize[globalpicnum]; - off.x = (float)((int32_t)tspr->xoffset + (flag ? h_xoffs[globalpicnum] : picanm[globalpicnum].xofs)); - off.y = (float)((int32_t)tspr->yoffset + (flag ? h_yoffs[globalpicnum] : picanm[globalpicnum].yofs)); - } - - int32_t method = DAMETH_MASK | DAMETH_CLAMPED; - - if (tspr->cstat & CSTAT_SPRITE_TRANSLUCENT) - method = DAMETH_CLAMPED | ((tspr->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT) ? DAMETH_TRANS2 : DAMETH_TRANS1); - - handle_blend(!!(tspr->cstat & CSTAT_SPRITE_TRANSLUCENT), tspr->blend, !!(tspr->cstat & CSTAT_SPRITE_TRANSLUCENT_INVERT)); - - drawpoly_alpha = spriteext[spritenum].alpha; - drawpoly_blend = tspr->blend; - - sec = (usectortype *)§or[tspr->sectnum]; - - polymost2_calc_fog(fogshade(globalshade, globalpal), sec->visibility, get_floor_fogpal(sec)); - - //POGOTODO: this while is an if statement - while (!(spriteext[spritenum].flags & SPREXT_NOTMD)) - { - //POGOTODO: switch these to if/else for readability and rearrange for performance - if (usemodels && tile2model[Ptile2tile(tspr->picnum, tspr->pal)].modelid >= 0 && - tile2model[Ptile2tile(tspr->picnum, tspr->pal)].framenum >= 0) - { - if (polymost_mddraw(tspr)) return; - break; // else, render as flat sprite - } - - if (usevoxels && (tspr->cstat & CSTAT_SPRITE_ALIGNMENT) != CSTAT_SPRITE_ALIGNMENT_SLAB && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]]) - { - if (polymost_voxdraw(voxmodels[tiletovox[tspr->picnum]], tspr)) return; - break; // else, render as flat sprite - } - - if ((tspr->cstat & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_SLAB && voxmodels[tspr->picnum]) - { - polymost_voxdraw(voxmodels[tspr->picnum], tspr); - return; - } - - break; - } - - //POGO: some comments seem to indicate that spinning sprites were intended to be supported before the - // decision was made to implement that behaviour with voxels. - // Skip SLAB aligned sprites when not rendering as voxels. - if ((globalorientation & CSTAT_SPRITE_ALIGNMENT) == CSTAT_SPRITE_ALIGNMENT_SLAB) - { - return; - } - - vec2_t pos = *(vec2_t *)tspr; - - if (spriteext[spritenum].flags & SPREXT_AWAY1) - { - pos.x += (sintable[(tspr->ang + 512) & 2047] >> 13); - pos.y += (sintable[(tspr->ang) & 2047] >> 13); - } - else if (spriteext[spritenum].flags & SPREXT_AWAY2) - { - pos.x -= (sintable[(tspr->ang + 512) & 2047] >> 13); - pos.y -= (sintable[(tspr->ang) & 2047] >> 13); - } - - vec2s_t const oldsiz = tilesiz[globalpicnum]; - vec2_t tsiz = { oldsiz.x, oldsiz.y }; - - if (usehightile && h_xsize[globalpicnum]) - { - tsiz.x = h_xsize[globalpicnum]; - tsiz.y = h_ysize[globalpicnum]; - } - - if (tsiz.x <= 0 || tsiz.y <= 0) - return; - - vec2f_t const ftsiz = { (float) tsiz.x, (float) tsiz.y }; - - //POGOTODO: some of these cases where we return could be done further up in order to skip doing throw away computation - if ((globalorientation & CSTAT_SPRITE_ALIGNMENT_FLOOR) && - (globalorientation & CSTAT_SPRITE_ONE_SIDED) != 0 && - (globalposz > tspr->z) == (!(globalorientation & CSTAT_SPRITE_YFLIP))) - { - return; - } - - //POGOTODO: in polymost1 any sprites that are too close are pre-clipped here before any calculation - - tilesiz[globalpicnum].x = tsiz.x; - tilesiz[globalpicnum].y = tsiz.y; - - float texScale[2] = {1.0f, -1.0f}; - float texOffset[2] = {((float) (spriteext[spritenum].xpanning) * (1.0f / 255.f)), - ((float) (spriteext[spritenum].ypanning) * (1.0f / 255.f))}; - - float transformMatrix[4*4] = - { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - }; - - float modelViewMatrix[4*4] = - { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - }; - - float f = (65536.f*512.f) / (fxdimen*viewingrange); - float g = 32.f / (fxdimen*gxyaspect); - - float horzScale = ftsiz.x*(1.f/64.f); - float vertScale = ftsiz.y*(1.f/64.f); - - horzScale *= ((float)tspr->xrepeat) * (1.f/64.f); - vertScale *= ((float)tspr->yrepeat) * (1.f/64.f); - - if ((globalorientation & CSTAT_SPRITE_ALIGNMENT)==CSTAT_SPRITE_ALIGNMENT_FACING) - { - horzScale *= 256.f/320.f; - } - else if ((globalorientation & CSTAT_SPRITE_ALIGNMENT)==CSTAT_SPRITE_ALIGNMENT_FLOOR) - { - //POGOTODO: fix floor sprites to be scaled up slightly by the right amount, and note their tex is slightly clipped on the leading edges - vertScale += 1.f/320.f; - } - - horzScale *= f; - vertScale *= g; - - //handle sprite flipping - horzScale *= -2.f*((globalorientation & CSTAT_SPRITE_XFLIP) != 0) + 1.f; - vertScale *= -2.f*(((globalorientation & CSTAT_SPRITE_ALIGNMENT) != CSTAT_SPRITE_ALIGNMENT_FLOOR) & - ((globalorientation & CSTAT_SPRITE_YFLIP) != 0)) + 1.f; - - //POGOTODO: replace this with simply using off.x and a different float for z offsets - // switching that over should fix floor sprite offsets so that they flip properly when yflip/xflip is applied - //handle orientation offsets - vec2f_t orientationOffset = {0.f, 0.f}; - vec3f_t offs = { 0.f, 0.f, 0.f }; - - off.x = 0.2f * ((float)tspr->xrepeat) * (((float) off.x) + (tsiz.x & 1)*0.5f*(((globalorientation & CSTAT_SPRITE_XFLIP) == 0)*-2.f + 1.f)); - off.y = 4.f * ((float)tspr->yrepeat) * (((float) off.y) + (((globalorientation & CSTAT_SPRITE_YCENTER) != 0) & tsiz.y & 1)*0.5f); - - int16_t angle = globalang; - float combinedClipScale = 1.f; - if ((globalorientation & CSTAT_SPRITE_ALIGNMENT)==CSTAT_SPRITE_ALIGNMENT_FACING) - { - int const ang = (getangle(tspr->x - globalposx, tspr->y - globalposy) + 1024) & 2047; - float const foffs = TSPR_OFFSET(tspr); - offs = { (float) (sintable[(ang + 512) & 2047] >> 6) * foffs, - (float) (sintable[(ang) & 2047] >> 6) * foffs, - 0.f}; - } - else if ((globalorientation & CSTAT_SPRITE_ALIGNMENT)==CSTAT_SPRITE_ALIGNMENT_WALL) - { - angle = (tspr->ang+1024)&2047; - /*float const foffs = TSPR_OFFSET(tspr); - offs = { (float) (sintable[(tspr->ang + 512) & 2047] >> 6) * foffs, - (float) (sintable[(tspr->ang) & 2047] >> 6) * foffs};*/ - - //POGOTODO: For now, just handle this exactly the same way as in polymost1. - // Eventually, I should change how all sprites avoid z-fighting by offsetting the z-buffer depth - // rather than offsetting the entire object in space. - vec2f_t const extent = { (float)tspr->xrepeat * (float)sintable[(tspr->ang) & 2047] * (1.0f / 65536.f), - (float)tspr->xrepeat * (float)sintable[(tspr->ang + 1536) & 2047] * (1.0f / 65536.f) }; - //POGOTODO: this needs to be calculated before I make my adjustments to off.x above! - float f = (float)(tsiz.x >> 1) + (float)off.x; - vec2f_t const vf = { extent.x * f, extent.y * f }; - - int32_t const s = tspr->owner; - int32_t walldist = 1; - int32_t w = (s == -1) ? -1 : wsprinfo[s].wall; - - // find the wall most likely to be what the sprite is supposed to be ornamented against - // this is really slow, so cache the result - if (s == -1 || !wsprinfo[s].wall || (spritechanged[s] != wsprinfo[s].srev) || - (w != -1 && wallchanged[w] != wsprinfo[s].wrev)) - { - w = polymost_findwall(tspr, &tsiz, &walldist); - - if (s != -1) - { - wallspriteinfo_t *ws = &wsprinfo[s]; - ws->wall = w; - - if (w != -1) - { - ws->wdist = walldist; - ws->wrev = wallchanged[w]; - ws->srev = spritechanged[s]; - } - } - } - else if (s != -1) - walldist = wsprinfo[s].wdist; - - // detect if the sprite is either on the wall line or the wall line and sprite intersect - if (w != -1) - { - vec2_t v = { /*Blrintf(vf.x)*/(int)vf.x, /*Blrintf(vf.y)*/(int)vf.y }; - - if (walldist <= 2 || ((pos.x - v.x) + (pos.x + v.x)) == (wall[w].x + POINT2(w).x) || - ((pos.y - v.y) + (pos.y + v.y)) == (wall[w].y + POINT2(w).y) || - polymost_lintersect(pos.x - v.x, pos.y - v.y, pos.x + v.x, pos.y + v.y, wall[w].x, wall[w].y, - POINT2(w).x, POINT2(w).y)) - { - int32_t const ang = getangle(wall[w].x - POINT2(w).x, wall[w].y - POINT2(w).y); - float const foffs = TSPR_OFFSET(tspr); - offs = { -(float)(sintable[(ang + 1024) & 2047] >> 6) * foffs, - -(float)(sintable[(ang + 512) & 2047] >> 6) * foffs, - 0.f}; - } - } - - //POGO: for full compatibility, facing sprites should also clip similarly (see polymost_drawsprite()) - // Clip sprites to ceilings/floors when no parallaxing - float fullCenterYOff = off.y + (((globalorientation & CSTAT_SPRITE_YCENTER) != 0) * 2.f) - * ftsiz.y * ((float)tspr->yrepeat); - if ((!(sector[tspr->sectnum].ceilingstat & 1)) && - sector[tspr->sectnum].ceilingz > tspr->z + fullCenterYOff - ((tspr->yrepeat * tsiz.y) << 2)) - { - float clipScale = ((float) (tspr->z + fullCenterYOff - sector[tspr->sectnum].ceilingz))/((float)((tspr->yrepeat * tsiz.y) << 2)); - if (clipScale <= 0.f) - { - //don't draw sprites fully clipped by the ceiling - return; - } - - texScale[1] *= clipScale; - texOffset[1] += (1.f-clipScale)*(-1.f*((globalorientation & CSTAT_SPRITE_YFLIP) == CSTAT_SPRITE_YFLIP)); - vertScale *= clipScale; - combinedClipScale *= clipScale; - } - if ((!(sector[tspr->sectnum].floorstat & 1)) && - sector[tspr->sectnum].floorz < tspr->z + fullCenterYOff) - { - float span = ((tspr->yrepeat * tsiz.y) << 2) - (tspr->z + fullCenterYOff - sector[tspr->sectnum].floorz); - float clipScale = span/((float)((tspr->yrepeat * tsiz.y) << 2)); - if (clipScale <= 0.f) - { - //don't draw sprites fully clipped by the floor - return; - } - - texScale[1] *= clipScale; - texOffset[1] += (1.f-clipScale)*(-1.f*((globalorientation & CSTAT_SPRITE_YFLIP) != CSTAT_SPRITE_YFLIP)); - vertScale *= clipScale; - combinedClipScale *= clipScale; - off.y += (float) (((tspr->yrepeat * tsiz.y) << 2) - span); - } - if (globalorientation & CSTAT_SPRITE_YCENTER) - { - combinedClipScale = 1.f; - } - } - - off.x *= ((float) ((globalorientation & CSTAT_SPRITE_XFLIP) != 0))*-2.f + 1.f; - off.y *= ((float) (((globalorientation & CSTAT_SPRITE_ALIGNMENT) != CSTAT_SPRITE_ALIGNMENT_FACING) & - ((globalorientation & CSTAT_SPRITE_YFLIP) != 0)))*-2.f + 1.f; - - if ((globalorientation & CSTAT_SPRITE_ALIGNMENT)==CSTAT_SPRITE_ALIGNMENT_FLOOR) - { - vertScale = -vertScale; - orientationOffset.x += ftsiz.y*((float) tspr->yrepeat)*(1.f/8.f); - - // unfortunately, offsetting by only 1 isn't enough on most Android devices - if (tspr->z == sec->ceilingz || tspr->z == sec->ceilingz + 1) - tspr->z = sec->ceilingz + 2, orientationOffset.y += (tspr->owner & 31); - - if (tspr->z == sec->floorz || tspr->z == sec->floorz - 1) - tspr->z = sec->floorz - 2, orientationOffset.y -= ((tspr->owner & 31)); - - angle = tspr->ang; - } - else - { - off.y -= (((globalorientation & CSTAT_SPRITE_YCENTER) != 0) * 2.f + - ((globalorientation & CSTAT_SPRITE_YFLIP) != 0)*-4.f) - * combinedClipScale * ftsiz.y * ((float)tspr->yrepeat); - } - - vec3f_t a0; - a0.x = ((float)(pos.y-globalposy)+offs.y) * -(1.f/1024.f)*-f; - a0.y = ((float)(pos.x-globalposx)+offs.x) * (1.f/1024.f)*f; - a0.z = ((float)(tspr->z-globalposz)+offs.z) * -(1.f/16384.f)*g; - orientationOffset.x *= -(1.f/1024.f)*-f; - orientationOffset.y *= -(1.f/16384.f)*g; - calcmat(a0, &orientationOffset, f, modelViewMatrix, angle); - - if ((globalorientation & CSTAT_SPRITE_ALIGNMENT)==CSTAT_SPRITE_ALIGNMENT_FLOOR) - { - float temp = modelViewMatrix[4]; modelViewMatrix[4] = modelViewMatrix[8]*16.f; modelViewMatrix[8] = -temp*(1.f/16.f); - temp = modelViewMatrix[5]; modelViewMatrix[5] = modelViewMatrix[9]*16.f; modelViewMatrix[9] = -temp*(1.f/16.f); - temp = modelViewMatrix[6]; modelViewMatrix[6] = modelViewMatrix[10]*16.f; modelViewMatrix[10] = -temp*(1.f/16.f); - } - - // mirrors - if (grhalfxdown10x < 0) - { - modelViewMatrix[0] = -modelViewMatrix[0]; modelViewMatrix[4] = -modelViewMatrix[4]; modelViewMatrix[8] = -modelViewMatrix[8]; modelViewMatrix[12] = -modelViewMatrix[12]; - } - - float ratio = 1.0f/get_projhack_ratio(); - float projectionMatrix[4*4] = - { - fydimen * ratio, 0.0f, 1.0f, 0.0f, - 0.0f, fxdimen, 1.0f, 0.0f, - 0.0f, 0.0f, 1.0f, fydimen * ratio, - 0.0f, 0.0f, -1.0f, 0.0f - }; - - float scaleMatrix[4*4] = - { - horzScale, 0.0f, 0.0f, 0.0f, - 0.0f, vertScale, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - }; - float offsetMatrix[4*4] = - { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - -off.x*(1.f/1024.f)*f, off.y * (1.f/16384.f)*g, 0.0f, 1.0f - }; - - multiplyMatrix4f(transformMatrix, scaleMatrix); - multiplyMatrix4f(transformMatrix, offsetMatrix); - //POGOTODO: for later optimization purposes (batching/caching), I need to split the modelViewMatrix into modelMatrix and viewMatrix - multiplyMatrix4f(transformMatrix, modelViewMatrix); - - //POGOTODO: I should instead implement one-sided sprites & culling by switching the xflip/yflip from flipping scale to instead flipping texScale - // Doing that will allow me to simplify a lot of this code, but it will require a lot of changes - polymost2_drawVBO(GL_TRIANGLE_STRIP, - quadVertsID, - 0, - 4, - projectionMatrix, - transformMatrix, - method, - texScale, - texOffset, - ((globalorientation & CSTAT_SPRITE_ONE_SIDED) != 0)*3 & - ((((globalorientation & CSTAT_SPRITE_XFLIP) != 0) ^ - ((globalorientation & CSTAT_SPRITE_YFLIP) != 0))+1)); - - drawpoly_srepeat = 0; - drawpoly_trepeat = 0; - - tilesiz[globalpicnum] = oldsiz; -} void polymost_drawsprite(int32_t snum) { - if (r_enablepolymost2) - { - polymost2_drawsprite(snum); - return; - } - uspritetype *const tspr = tspriteptr[snum]; if (EDUKE32_PREDICT_FALSE(bad_tspr(tspr))) diff --git a/source/build/src/sdlayer.cpp b/source/build/src/sdlayer.cpp index 929cee4fa..3f3e3b7a7 100644 --- a/source/build/src/sdlayer.cpp +++ b/source/build/src/sdlayer.cpp @@ -1763,14 +1763,26 @@ void videoShowFrame(int32_t w) glsurface_blitBuffer(); } + static uint32_t lastSwapTime = 0; +#ifdef TIMING + cycle_t clock; + clock.Reset(); + clock.Clock(); +#endif + glFinish(); +#ifdef TIMING + clock.Unclock(); + OSD_Printf("glfinish time: %2.3f\n", clock.TimeMS()); +#endif SDL_GL_SwapWindow(sdl_window); + /* if (vsync) { - static uint32_t lastSwapTime = 0; // busy loop until we're ready to update again while (SDL_GetTicks()-lastSwapTime < currentVBlankInterval) {} - lastSwapTime = SDL_GetTicks(); } + */ + lastSwapTime = SDL_GetTicks(); return; } #endif diff --git a/source/build/src/texcache.cpp b/source/build/src/texcache.cpp index 72721f277..889d1d386 100644 --- a/source/build/src/texcache.cpp +++ b/source/build/src/texcache.cpp @@ -76,7 +76,17 @@ static pthtyp *texcache_tryart(int32_t const dapicnum, int32_t const dapalnum, i pth = (pthtyp *)Xcalloc(1,sizeof(pthtyp)); - gloadtile_art(dapicnum, searchpalnum, tintpalnum, dashade, dameth, pth, 1); +#ifdef TIMING + cycle_t clock; + clock.Reset(); + clock.Clock(); +#endif + gloadtile_art(dapicnum, searchpalnum, tintpalnum, dashade, dameth, pth, 1); + //thl.AddToCache(dapicnum, dapalnum, dameth); +#ifdef TIMING + clock.Unclock(); + OSD_Printf("Loaded texture %d, palnum %d, meth %d -> %2.3f\n", dapicnum, dapalnum, dameth, clock.TimeMS()); +#endif pth->palnum = dapalnum; pth->next = texcache.list[j]; @@ -181,9 +191,16 @@ pthtyp *texcache_fetch(int32_t dapicnum, int32_t dapalnum, int32_t dashade, int3 if (dapalnum == DETAILPAL && texcache_fetchmulti(pth, si, dapicnum, dameth)) return pth; - int32_t tilestat = - gloadtile_hi(dapicnum, dapalnum, drawingskybox, si, dameth, pth, 1, (checktintpal > 0) ? 0 : tintflags); - +#ifdef TIMING + cycle_t clock; + clock.Reset(); + clock.Clock(); +#endif + int32_t tilestat = gloadtile_hi(dapicnum, dapalnum, drawingskybox, si, dameth, pth, 1, (checktintpal > 0) ? 0 : tintflags); +#ifdef TIMING + clock.Unclock(); + OSD_Printf("Loaded texture %d, palnum %d, meth %d -> %2.3f\n", dapicnum, dapalnum, dameth, clock.TimeMS()); +#endif if (!tilestat) { pth->next = texcache.list[j]; diff --git a/source/build/src/winbits.cpp b/source/build/src/winbits.cpp index e3bb7e44d..114dc6f46 100644 --- a/source/build/src/winbits.cpp +++ b/source/build/src/winbits.cpp @@ -253,10 +253,11 @@ void win_close(void) } -// Keyboard layout switching +// Keyboard layout switching (disable because this is rude.) static void switchlayout(char const * layout) { + /* char layoutname[KL_NAMELENGTH]; GetKeyboardLayoutName(layoutname); @@ -266,17 +267,19 @@ static void switchlayout(char const * layout) initprintf("Switching keyboard layout from %s to %s\n", layoutname, layout); LoadKeyboardLayout(layout, KLF_ACTIVATE|KLF_SETFORPROCESS|KLF_SUBSTITUTE_OK); + */ } static char OriginalLayoutName[KL_NAMELENGTH]; void Win_GetOriginalLayoutName(void) { - GetKeyboardLayoutName(OriginalLayoutName); + //GetKeyboardLayoutName(OriginalLayoutName); } void Win_SetKeyboardLayoutUS(int const toggle) { + /* static int currentstate; if (toggle != currentstate) @@ -293,6 +296,7 @@ void Win_SetKeyboardLayoutUS(int const toggle) currentstate = toggle; } } + */ } @@ -411,6 +415,78 @@ int32_t win_buildargs(char **argvbuf) } +//========================================================================== +// +// CalculateCPUSpeed +// +// Make a decent guess at how much time elapses between TSC steps. This can +// vary over runtime depending on power management settings, so should not +// be used anywhere that truely accurate timing actually matters. +// +//========================================================================== + +double PerfToSec, PerfToMillisec; +#include "stats.h" + +static void CalculateCPUSpeed() +{ + LARGE_INTEGER freq; + + QueryPerformanceFrequency(&freq); + + if (freq.QuadPart != 0) + { + LARGE_INTEGER count1, count2; + cycle_t ClockCalibration; + DWORD min_diff; + + ClockCalibration.Reset(); + + // Count cycles for at least 55 milliseconds. + // The performance counter may be very low resolution compared to CPU + // speeds today, so the longer we count, the more accurate our estimate. + // On the other hand, we don't want to count too long, because we don't + // want the user to notice us spend time here, since most users will + // probably never use the performance statistics. + min_diff = freq.LowPart * 11 / 200; + + // Minimize the chance of task switching during the testing by going very + // high priority. This is another reason to avoid timing for too long. + SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + + // Make sure we start timing on a counter boundary. + QueryPerformanceCounter(&count1); + do + { + QueryPerformanceCounter(&count2); + } while (count1.QuadPart == count2.QuadPart); + + // Do the timing loop. + ClockCalibration.Clock(); + do + { + QueryPerformanceCounter(&count1); + } while ((count1.QuadPart - count2.QuadPart) < min_diff); + ClockCalibration.Unclock(); + + SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); + + PerfToSec = double(count1.QuadPart - count2.QuadPart) / (double(ClockCalibration.GetRawCounter()) * freq.QuadPart); + PerfToMillisec = PerfToSec * 1000.0; + } +} + +class Initer +{ +public: + Initer() { CalculateCPUSpeed(); } +}; + +static Initer initer; + + // Workaround for a bug in mingwrt-4.0.0 and up where a function named main() in misc/src/libcrt/gdtoa/qnan.c takes precedence over the proper one in src/libcrt/crt/main.c. #if (defined __MINGW32__ && EDUKE32_GCC_PREREQ(4,8)) || EDUKE32_CLANG_PREREQ(3,4) # undef main