From 6dc35f956309dd34592c6c906f525f1805d66120 Mon Sep 17 00:00:00 2001 From: Bart Trzynadlowski Date: Wed, 25 May 2016 03:10:36 +0000 Subject: [PATCH] Updated legacy engine vertex shader to use specular shininess and coefficient along with old equation. Still not correct (too strong compared to the old method). --- Src/Graphics/Legacy3D/Models.cpp | 5 +- Src/Graphics/Legacy3D/Shaders/Vertex.glsl | 30 +- Src/Graphics/Legacy3D/Shaders3D.h | 842 +++++++++++----------- 3 files changed, 467 insertions(+), 410 deletions(-) diff --git a/Src/Graphics/Legacy3D/Models.cpp b/Src/Graphics/Legacy3D/Models.cpp index 9d94376..db73cc9 100644 --- a/Src/Graphics/Legacy3D/Models.cpp +++ b/Src/Graphics/Legacy3D/Models.cpp @@ -673,7 +673,8 @@ void CLegacy3D::InsertVertex(ModelCache *Cache, const Vertex *V, const Poly *P, // Specular shininess GLfloat specularCoefficient = (GLfloat) ((P->header[0]>>26) & 0x3F) * (1.0f/63.0f); - int shininess = (P->header[6] >> 5) & 3; + int shinyBits = (P->header[6] >> 5) & 3; + float shininess = pow(2.0, 1+shinyBits); if (!(P->header[0]&0x80)) //|| (shininess == 0)) // bit 0x80 seems to enable specular lighting { specularCoefficient = 0.; // disable @@ -689,7 +690,7 @@ void CLegacy3D::InsertVertex(ModelCache *Cache, const Vertex *V, const Poly *P, GLfloat fogIntensity = (GLfloat) ((P->header[6]>>11)&0x1F) * (1.0f/31.0f); if (!(P->header[6]&0x00010000)) // if not luminous, always use full fog intensity fogIntensity = 1.0f; - + /* * Contour processing. Any alpha value sufficiently close to 0 seems to * cause pixels to be discarded entirely on Model 3 (no modification of the diff --git a/Src/Graphics/Legacy3D/Shaders/Vertex.glsl b/Src/Graphics/Legacy3D/Shaders/Vertex.glsl index 8489abd..7467370 100644 --- a/Src/Graphics/Legacy3D/Shaders/Vertex.glsl +++ b/Src/Graphics/Legacy3D/Shaders/Vertex.glsl @@ -42,7 +42,8 @@ attribute float texFormat; // T1RGB5 contour texture (if > 0) attribute float texMap; // texture map number attribute float transLevel; // translucence level, 0.0 (transparent) to 1.0 (opaque). if less than 1.0, replace alpha value attribute float lightEnable; // lighting enabled (1.0) or luminous (0.0), drawn at full intensity -attribute float shininess; // specular shininess (if >= 0.0) or disable specular lighting (negative) +attribute float specular; // specular coefficient (0.0 if disabled) +attribute float shininess; // specular shininess attribute float fogIntensity; // fog intensity (1.0, full fog effect, 0.0, no fog) // Custom outputs to fragment shader @@ -145,11 +146,38 @@ void main(void) if (shininess >= 0.0) { // Standard specular lighting equation + if (sunFactor > 0.0) + { + vec3 V = normalize(-viewVertex); + vec3 H = normalize(sunVector+V); // halfway vector + fsSpecularTerm = specular*pow(max(dot(viewNormal,H),0.0),shininess); + + // Phong formula + // vec3 R = normalize(2.0*dot(sunVector,viewNormal)*viewNormal - sunVector); + // vec3 V = normalize(-viewVertex); + // fsSpecularTerm = lighting[1].x * specular * pow(max(dot(R,V),0.0),4.); + + // + // This looks decent in Scud Race attract mode. It is directionally + // correct (highlights appear in the right places under the same + // conditions as the actual game). In game play, it no longer works. + // This is loosely based on the Model 2 formula, which is: + // + // s = 2*dot(light, normal)*normal.z - light.z + // + // float dot1 = dot(sunVector, viewNormal); + // float s = dot1*viewNormal.z; + // fsSpecularTerm =specular * pow(max(s, 0.0), 2.); + // + } + + /* vec3 V = normalize(-viewVertex); vec3 H = normalize(sunVector+V); // halfway vector float s = max(10.0,64.0-shininess); // seems to look nice, but probably not correct fsSpecularTerm = pow(max(dot(viewNormal,H),0.0),s); if (sunFactor <= 0.0) fsSpecularTerm = 0.0; + */ // Faster approximation //float temp = max(dot(viewNormal,H),0.0); diff --git a/Src/Graphics/Legacy3D/Shaders3D.h b/Src/Graphics/Legacy3D/Shaders3D.h index 4a9c433..a625a77 100644 --- a/Src/Graphics/Legacy3D/Shaders3D.h +++ b/Src/Graphics/Legacy3D/Shaders3D.h @@ -63,156 +63,184 @@ static const char vertexShaderSource[] = "#version 120\n" "\n" "// Global uniforms\n" -"uniform mat4\tmodelViewMatrix;\t// model -> view space matrix\n" -"uniform mat4\tprojectionMatrix;\t// view space -> screen space matrix\n" -"uniform vec3\tlighting[2];\t\t// lighting state (lighting[0] = sun direction, lighting[1].x,y = diffuse, ambient intensities from 0-1.0)\n" -"uniform vec4\tspotEllipse;\t\t// spotlight ellipse position: .x=X position (normalized device coordinates), .y=Y position, .z=half-width, .w=half-height)\n" -"uniform vec2\tspotRange;\t\t\t// spotlight Z range: .x=start (viewspace coordinates), .y=limit\n" -"uniform vec3\tspotColor;\t\t\t// spotlight RGB color\n" +"uniform mat4 modelViewMatrix; // model -> view space matrix\n" +"uniform mat4 projectionMatrix; // view space -> screen space matrix\n" +"uniform vec3 lighting[2]; // lighting state (lighting[0] = sun direction, lighting[1].x,y = diffuse, ambient intensities from 0-1.0)\n" +"uniform vec4 spotEllipse; // spotlight ellipse position: .x=X position (normalized device coordinates), .y=Y position, .z=half-width, .w=half-height)\n" +"uniform vec2 spotRange; // spotlight Z range: .x=start (viewspace coordinates), .y=limit\n" +"uniform vec3 spotColor; // spotlight RGB color\n" "\n" "// Custom vertex attributes\n" -"attribute vec4\tsubTexture;\t\t// .x=texture X, .y=texture Y, .z=texture width, .w=texture height (all in texels)\n" -"attribute vec4\ttexParams;\t\t// .x=texture enable (if 1, else 0), .y=use transparency (if >=0), .z=U wrap mode (1=mirror, 0=repeat), .w=V wrap mode\n" -"attribute float\ttexFormat;\t\t// T1RGB5 contour texture (if > 0)\n" -"attribute float\ttexMap;\t\t// texture map number\n" -"attribute float\ttransLevel;\t\t// translucence level, 0.0 (transparent) to 1.0 (opaque). if less than 1.0, replace alpha value\n" -"attribute float\tlightEnable;\t// lighting enabled (1.0) or luminous (0.0), drawn at full intensity\n" -"attribute float\tshininess;\t\t// specular shininess (if >= 0.0) or disable specular lighting (negative)\n" -"attribute float\tfogIntensity;\t// fog intensity (1.0, full fog effect, 0.0, no fog) \n" +"attribute vec4 subTexture; // .x=texture X, .y=texture Y, .z=texture width, .w=texture height (all in texels)\n" +"attribute vec4 texParams; // .x=texture enable (if 1, else 0), .y=use transparency (if >=0), .z=U wrap mode (1=mirror, 0=repeat), .w=V wrap mode\n" +"attribute float texFormat; // T1RGB5 contour texture (if > 0)\n" +"attribute float texMap; // texture map number\n" +"attribute float transLevel; // translucence level, 0.0 (transparent) to 1.0 (opaque). if less than 1.0, replace alpha value\n" +"attribute float lightEnable; // lighting enabled (1.0) or luminous (0.0), drawn at full intensity\n" +"attribute float specular; // specular coefficient (0.0 if disabled)\n" +"attribute float shininess; // specular shininess\n" +"attribute float fogIntensity; // fog intensity (1.0, full fog effect, 0.0, no fog) \n" "\n" "// Custom outputs to fragment shader\n" -"varying vec4\tfsSubTexture;\n" -"varying vec4\tfsTexParams;\n" -"varying float\tfsTexFormat;\n" -"varying float\tfsTexMap;\n" -"varying float\tfsTransLevel;\n" -"varying vec3\tfsLightIntensity;\t// total light intensity for this vertex\n" -"varying float\tfsSpecularTerm;\t\t// specular light term (additive)\n" -"varying float\tfsFogFactor;\t\t// fog factor\n" -"varying float\tfsViewZ;\n" +"varying vec4 fsSubTexture;\n" +"varying vec4 fsTexParams;\n" +"varying float fsTexFormat;\n" +"varying float fsTexMap;\n" +"varying float fsTransLevel;\n" +"varying vec3 fsLightIntensity; // total light intensity for this vertex\n" +"varying float fsSpecularTerm; // specular light term (additive)\n" +"varying float fsFogFactor; // fog factor\n" +"varying float fsViewZ;\n" "\n" "// Gets the 3x3 matrix out of a 4x4 (because mat3(mat4matrix) does not work on ATI!)\n" "mat3 GetLinearPart( mat4 m )\n" "{\n" -"\tmat3 result;\n" -"\t\n" -"\tresult[0][0] = m[0][0]; \n" -"\tresult[0][1] = m[0][1]; \n" -"\tresult[0][2] = m[0][2]; \n" +" mat3 result;\n" +" \n" +" result[0][0] = m[0][0];\n" +" result[0][1] = m[0][1];\n" +" result[0][2] = m[0][2];\n" "\n" -"\tresult[1][0] = m[1][0]; \n" -"\tresult[1][1] = m[1][1]; \n" -"\tresult[1][2] = m[1][2]; \n" -"\t\n" -"\tresult[2][0] = m[2][0]; \n" -"\tresult[2][1] = m[2][1]; \n" -"\tresult[2][2] = m[2][2]; \n" -"\t\n" -"\treturn result;\n" +" result[1][0] = m[1][0];\n" +" result[1][1] = m[1][1];\n" +" result[1][2] = m[1][2];\n" +" \n" +" result[2][0] = m[2][0];\n" +" result[2][1] = m[2][1];\n" +" result[2][2] = m[2][2];\n" +" \n" +" return result;\n" "}\n" "\n" "void main(void)\n" "{\n" -"\tvec3\tviewVertex;\t\t// vertex coordinates in view space\n" -"\tvec3\tviewNormal;\t\t// vertex normal in view space\n" -"\tvec3\tsunVector;\t\t// sun lighting vector (as reflecting away from vertex)\n" -"\tfloat\tsunFactor;\t\t// sun light projection along vertex normal (0.0 to 1.0)\n" -"\tvec3\thalfway;\n" -"\tfloat\tspecFactor;\n" -"\t\n" -"\t// Transform vertex\n" -"\tgl_Position = projectionMatrix * modelViewMatrix * gl_Vertex;\n" -"\tviewVertex = vec3(modelViewMatrix * gl_Vertex);\t\n" -"\t\n" -"\t/*\n" -"\t * Modulation\n" -"\t *\n" -" \t * Polygon color serves as material color (modulating the light intensity)\n" -"\t * for textured polygons. The fragment shader will ignore (overwrite) the\n" -"\t * the color passed to it if the fragment is textured. \n" -"\t *\n" -"\t * Untextured fragments must be set to the polygon color and the light\n" -"\t * intensity is initialized to 1.0 here. Alpha must be set to 1.0 because\n" -"\t * the fragment shader multiplies it by the polygon translucency setting. \n" -"\t *\n" -"\t * TO-DO: Does OpenGL set alpha to 1.0 by default if no alpha is specified\n" -"\t * for the vertex? If so, we can remove that line from here.\n" -"\t */\n" +" vec3 viewVertex; // vertex coordinates in view space\n" +" vec3 viewNormal; // vertex normal in view space\n" +" vec3 sunVector; // sun lighting vector (as reflecting away from vertex)\n" +" float sunFactor; // sun light projection along vertex normal (0.0 to 1.0)\n" +" vec3 halfway;\n" +" float specFactor;\n" +" \n" +" // Transform vertex\n" +" gl_Position = projectionMatrix * modelViewMatrix * gl_Vertex;\n" +" viewVertex = vec3(modelViewMatrix * gl_Vertex); \n" +" \n" +" /*\n" +" * Modulation\n" +" *\n" +" * Polygon color serves as material color (modulating the light intensity)\n" +" * for textured polygons. The fragment shader will ignore (overwrite) the\n" +" * the color passed to it if the fragment is textured. \n" +" *\n" +" * Untextured fragments must be set to the polygon color and the light\n" +" * intensity is initialized to 1.0 here. Alpha must be set to 1.0 because\n" +" * the fragment shader multiplies it by the polygon translucency setting. \n" +" *\n" +" * TO-DO: Does OpenGL set alpha to 1.0 by default if no alpha is specified\n" +" * for the vertex? If so, we can remove that line from here.\n" +" */\n" "\n" -"\tgl_FrontColor = gl_Color;\t// untextured polygons will use this\n" -"\tgl_FrontColor.a = 1.0;\t\n" -"\tfsLightIntensity = vec3(1.0,1.0,1.0);\n" -"\tif (texParams.x > 0.5)\t\t// textured\n" -"\t\tfsLightIntensity *= gl_Color.rgb;\n" -"\t\t\n" -"\t/*\n" -" \t * Sun Light\n" -"\t *\n" -"\t * Parallel light source and ambient lighting are only applied for non-\n" -"\t * luminous polygons.\n" -" \t */\n" -"\tfsSpecularTerm = 0.0;\n" -" \tif (lightEnable > 0.5)\t// not luminous\n" -"\t{\n" -"\t\t// Normal -> view space\n" -"\t\tviewNormal = normalize(GetLinearPart(modelViewMatrix)*gl_Normal);\n" +" gl_FrontColor = gl_Color; // untextured polygons will use this\n" +" gl_FrontColor.a = 1.0; \n" +" fsLightIntensity = vec3(1.0,1.0,1.0);\n" +" if (texParams.x > 0.5) // textured\n" +" fsLightIntensity *= gl_Color.rgb;\n" +" \n" +" /*\n" +" * Sun Light\n" +" *\n" +" * Parallel light source and ambient lighting are only applied for non-\n" +" * luminous polygons.\n" +" */\n" +" fsSpecularTerm = 0.0;\n" +" if (lightEnable > 0.5) // not luminous\n" +" {\n" +" // Normal -> view space\n" +" viewNormal = normalize(GetLinearPart(modelViewMatrix)*gl_Normal);\n" "\n" -"\t\t// Real3D -> OpenGL view space convention (TO-DO: do this outside of shader)\n" -"\t\tsunVector = lighting[0]*vec3(1.0,-1.0,-1.0);\n" -"\t\t\n" -"\t\t// Compute diffuse factor for sunlight\n" -"\t\tsunFactor = max(dot(sunVector,viewNormal),0.0);\n" -"\t\t\n" -"\t\t// Total light intensity: sum of all components\n" -"\t\tfsLightIntensity *= min(1.0,(sunFactor*lighting[1].x+lighting[1].y));\n" -"\t\t\n" -"\t\t/*\n" -"\t\t * Specular Lighting\n" -"\t\t *\n" -"\t\t * The specular term is treated similarly to the \"separate specular\n" -"\t\t * color\" functionality of OpenGL: it is added as a highlight in the\n" -"\t\t * fragment shader. This allows even black textures to be lit.\n" -"\t\t *\n" -"\t\t * TO-DO: Ambient intensity viewport parameter is known but what about\n" -"\t\t * the intensity of the specular term? Always applied with full \n" -"\t\t * intensity here but this is unlikely to be correct.\n" -"\t\t */\n" -" \t\tif (shininess >= 0.0)\n" -" \t\t{\n" -" \t\t\t// Standard specular lighting equation\n" -" \t\t\tvec3 V = normalize(-viewVertex);\n" -" \t\t\tvec3 H = normalize(sunVector+V);\t// halfway vector\n" -" \t\t\tfloat s = max(10.0,64.0-shininess);\t\t// seems to look nice, but probably not correct\n" -" \t\t\tfsSpecularTerm = pow(max(dot(viewNormal,H),0.0),s);\n" -" \t\t\tif (sunFactor <= 0.0) fsSpecularTerm = 0.0;\n" -" \t\t\t\n" -" \t\t\t// Faster approximation \t\t\t\n" -" \t\t\t//float temp = max(dot(viewNormal,H),0.0);\n" -" \t\t\t//float s = 64.0-shininess;\n" -" \t\t\t//fsSpecularTerm = temp/(s-temp*s+temp);\n" -" \t\t\t\n" -" \t\t\t// Phong formula\n" -" \t\t\t//vec3 R = normalize(2.0*dot(sunVector,viewNormal)*viewNormal - sunVector);\n" -" \t\t\t//vec3 V = normalize(-viewVertex);\n" -" \t\t\t//float s = max(2.0,64.0-shininess);\n" -" \t\t\t//fsSpecularTerm = pow(max(dot(R,V),0.0),s);\n" -" \t\t}\n" -"\t}\n" -"\t\n" -"\t// Fog\n" -"\tfloat z = length(viewVertex);\n" -"\tfsFogFactor = clamp(1.0-fogIntensity*(gl_Fog.start+z*gl_Fog.density), 0.0, 1.0);\n" +" // Real3D -> OpenGL view space convention (TO-DO: do this outside of shader)\n" +" sunVector = lighting[0]*vec3(1.0,-1.0,-1.0);\n" "\n" -"\t// Pass viewspace Z coordinate (for spotlight)\n" -"\tfsViewZ = -viewVertex.z;\t// convert Z from GL->Real3D convention (want +Z to be further into screen)\n" +" // Compute diffuse factor for sunlight\n" +" sunFactor = max(dot(sunVector,viewNormal),0.0);\n" "\n" -"\t// Pass remaining parameters to fragment shader\n" -"\tgl_TexCoord[0] = gl_MultiTexCoord0;\n" -"\tfsSubTexture = subTexture;\n" -"\tfsTexParams = texParams;\n" -"\tfsTransLevel = transLevel;\n" -"\tfsTexFormat = texFormat;\n" -"\tfsTexMap = texMap;\n" +" // Total light intensity: sum of all components\n" +" fsLightIntensity *= min(1.0,(sunFactor*lighting[1].x+lighting[1].y));\n" +"\n" +" /*\n" +" * Specular Lighting\n" +" *\n" +" * The specular term is treated similarly to the \"separate specular\n" +" * color\" functionality of OpenGL: it is added as a highlight in the\n" +" * fragment shader. This allows even black textures to be lit.\n" +" *\n" +" * TO-DO: Ambient intensity viewport parameter is known but what about\n" +" * the intensity of the specular term? Always applied with full \n" +" * intensity here but this is unlikely to be correct.\n" +" */\n" +" if (shininess >= 0.0)\n" +" {\n" +" // Standard specular lighting equation\n" +" if (sunFactor > 0.0)\n" +" {\n" +" vec3 V = normalize(-viewVertex);\n" +" vec3 H = normalize(sunVector+V); // halfway vector\n" +" fsSpecularTerm = specular*pow(max(dot(viewNormal,H),0.0),shininess);\n" +"\n" +" // Phong formula\n" +" // vec3 R = normalize(2.0*dot(sunVector,viewNormal)*viewNormal - sunVector);\n" +" // vec3 V = normalize(-viewVertex);\n" +" // fsSpecularTerm = lighting[1].x * specular * pow(max(dot(R,V),0.0),4.);\n" +"\n" +" //\n" +" // This looks decent in Scud Race attract mode. It is directionally\n" +" // correct (highlights appear in the right places under the same\n" +" // conditions as the actual game). In game play, it no longer works.\n" +" // This is loosely based on the Model 2 formula, which is:\n" +" //\n" +" // s = 2*dot(light, normal)*normal.z - light.z\n" +" //\n" +" // float dot1 = dot(sunVector, viewNormal);\n" +" // float s = dot1*viewNormal.z;\n" +" // fsSpecularTerm =specular * pow(max(s, 0.0), 2.);\n" +" //\n" +" }\n" +"\n" +" /*\n" +" vec3 V = normalize(-viewVertex);\n" +" vec3 H = normalize(sunVector+V); // halfway vector\n" +" float s = max(10.0,64.0-shininess); // seems to look nice, but probably not correct\n" +" fsSpecularTerm = pow(max(dot(viewNormal,H),0.0),s);\n" +" if (sunFactor <= 0.0) fsSpecularTerm = 0.0;\n" +" */\n" +"\n" +" // Faster approximation\n" +" //float temp = max(dot(viewNormal,H),0.0);\n" +" //float s = 64.0-shininess;\n" +" //fsSpecularTerm = temp/(s-temp*s+temp);\n" +"\n" +" // Phong formula\n" +" //vec3 R = normalize(2.0*dot(sunVector,viewNormal)*viewNormal - sunVector);\n" +" //vec3 V = normalize(-viewVertex);\n" +" //float s = max(2.0,64.0-shininess);\n" +" //fsSpecularTerm = pow(max(dot(R,V),0.0),s);\n" +" }\n" +" }\n" +" \n" +" // Fog\n" +" float z = length(viewVertex);\n" +" fsFogFactor = clamp(1.0-fogIntensity*(gl_Fog.start+z*gl_Fog.density), 0.0, 1.0);\n" +"\n" +" // Pass viewspace Z coordinate (for spotlight)\n" +" fsViewZ = -viewVertex.z; // convert Z from GL->Real3D convention (want +Z to be further into screen)\n" +"\n" +" // Pass remaining parameters to fragment shader\n" +" gl_TexCoord[0] = gl_MultiTexCoord0;\n" +" fsSubTexture = subTexture;\n" +" fsTexParams = texParams;\n" +" fsTransLevel = transLevel;\n" +" fsTexFormat = texFormat;\n" +" fsTexMap = texMap;\n" "}\n" }; @@ -250,23 +278,23 @@ static const char fragmentShaderSingleSheetSource[] = "#version 120\n" "\n" "// Global uniforms\n" -"uniform sampler2D\ttextureMap;\t\t// complete texture map, 2048x2048 texels\n" -"uniform vec4\t\tspotEllipse;\t\t// spotlight ellipse position: .x=X position (screen coordinates), .y=Y position, .z=half-width, .w=half-height)\n" -"uniform vec2\t\tspotRange;\t\t// spotlight Z range: .x=start (viewspace coordinates), .y=limit\n" -"uniform vec3\t\tspotColor;\t\t// spotlight RGB color\n" -"uniform vec3\t\tlighting[2];\t\t// lighting state (lighting[0] = sun direction, lighting[1].x,y = diffuse, ambient intensities from 0-1.0)\n" -"uniform float\t\tmapSize;\t\t// texture map size (2048,4096,6144 etc)\n" +"uniform sampler2D textureMap; // complete texture map, 2048x2048 texels\n" +"uniform vec4 spotEllipse; // spotlight ellipse position: .x=X position (screen coordinates), .y=Y position, .z=half-width, .w=half-height)\n" +"uniform vec2 spotRange; // spotlight Z range: .x=start (viewspace coordinates), .y=limit\n" +"uniform vec3 spotColor; // spotlight RGB color\n" +"uniform vec3 lighting[2]; // lighting state (lighting[0] = sun direction, lighting[1].x,y = diffuse, ambient intensities from 0-1.0)\n" +"uniform float mapSize; // texture map size (2048,4096,6144 etc)\n" "\n" "// Inputs from vertex shader \n" -"varying vec4\t\tfsSubTexture;\t// .x=texture X, .y=texture Y, .z=texture width, .w=texture height (all in texels)\n" -"varying vec4\t\tfsTexParams;\t// .x=texture enable (if 1, else 0), .y=use transparency (if > 0), .z=U wrap mode (1=mirror, 0=repeat), .w=V wrap mode\n" -"varying float\t\tfsTexFormat;\t// T1RGB5 contour texture (if > 0)\n" -"varying float\t\tfsTexMap;\t\t// texture map number\n" -"varying float\t\tfsTransLevel;\t// translucence level, 0.0 (transparent) to 1.0 (opaque)\n" -"varying vec3\t\tfsLightIntensity;\t// lighting intensity \n" -"varying float\t\tfsSpecularTerm;\t// specular highlight\n" -"varying float\t\tfsFogFactor;\t// fog factor\n" -"varying float\t\tfsViewZ;\t\t// Z distance to fragment from viewpoint at origin\n" +"varying vec4 fsSubTexture; // .x=texture X, .y=texture Y, .z=texture width, .w=texture height (all in texels)\n" +"varying vec4 fsTexParams; // .x=texture enable (if 1, else 0), .y=use transparency (if > 0), .z=U wrap mode (1=mirror, 0=repeat), .w=V wrap mode\n" +"varying float fsTexFormat; // T1RGB5 contour texture (if > 0)\n" +"varying float fsTexMap; // texture map number\n" +"varying float fsTransLevel; // translucence level, 0.0 (transparent) to 1.0 (opaque)\n" +"varying vec3 fsLightIntensity; // lighting intensity \n" +"varying float fsSpecularTerm; // specular highlight\n" +"varying float fsFogFactor; // fog factor\n" +"varying float fsViewZ; // Z distance to fragment from viewpoint at origin\n" "\n" "/*\n" " * WrapTexelCoords():\n" @@ -282,7 +310,7 @@ static const char fragmentShaderSingleSheetSource[] = " * X, Y position to select the appropriate one, and normalize by 2048\n" " * (the dimensions of the Real3D texture sheet).\n" " *\n" -" *\t\t= [(u,v)%(w,h)+(x,y)]/(2048,2048)\n" +" * = [(u,v)%(w,h)+(x,y)]/(2048,2048)\n" " *\n" " * If mirroring is enabled, textures are mirrored every odd multiple of\n" " * the original texture. To detect whether we are in an odd multiple, \n" @@ -290,8 +318,8 @@ static const char fragmentShaderSingleSheetSource[] = " * whether the result is odd. Then, clamp the coordinates as before but\n" " * subtract from the last texel to mirror them:\n" " *\n" -" * \t\t= [M*((w-1,h-1)-(u,v)%(w,h)) + (1-M)*(u,v)%(w,h) + (x,y)]/(2048,2048)\n" -" *\t\twhere M is 1.0 if the texture must be mirrored.\n" +" * = [M*((w-1,h-1)-(u,v)%(w,h)) + (1-M)*(u,v)%(w,h) + (x,y)]/(2048,2048)\n" +" * where M is 1.0 if the texture must be mirrored.\n" " *\n" " * As an optimization, this function computes TWO texture coordinates\n" " * simultaneously. The first is texCoord.xy, the second is in .zw. The other\n" @@ -299,16 +327,16 @@ static const char fragmentShaderSingleSheetSource[] = " */\n" "vec4 WrapTexelCoords(vec4 texCoord, vec4 texOffset, vec4 texSize, vec4 mirrorEnable)\n" "{\n" -"\tvec4\tclampedCoord, mirror, glTexCoord;\n" -"\t\n" -"\tclampedCoord = mod(texCoord,texSize);\t\t\t\t\t\t// clamp coordinates to within texture size\n" -"\tmirror = mirrorEnable * mod(floor(texCoord/texSize),2.0);\t// whether this texel needs to be mirrored\n" +" vec4 clampedCoord, mirror, glTexCoord;\n" +" \n" +" clampedCoord = mod(texCoord,texSize); // clamp coordinates to within texture size\n" +" mirror = mirrorEnable * mod(floor(texCoord/texSize),2.0); // whether this texel needs to be mirrored\n" "\n" -"\tglTexCoord = (\tmirror*(texSize-clampedCoord) +\n" -"\t\t\t\t\t(vec4(1.0,1.0,1.0,1.0)-mirror)*clampedCoord +\n" -"\t\t\t\t\ttexOffset\n" -"\t\t\t\t ) / mapSize;\n" -"\treturn glTexCoord;\n" +" glTexCoord = ( mirror*(texSize-clampedCoord) +\n" +" (vec4(1.0,1.0,1.0,1.0)-mirror)*clampedCoord +\n" +" texOffset\n" +" ) / mapSize;\n" +" return glTexCoord;\n" "}\n" "\n" "/*\n" @@ -318,101 +346,101 @@ static const char fragmentShaderSingleSheetSource[] = " */\n" "\n" "void main(void)\n" -"{\t\n" -"\tvec4\tuv_top, uv_bot, c[4];\n" -"\tvec2\tr;\n" -"\tvec4\tfragColor;\n" -"\tvec2\tellipse;\n" -"\tvec3\tlightIntensity;\n" -"\tfloat\tinsideSpot;\n" -"\tint\t\tx;\n" -"\t\n" -"\t// Get polygon color for untextured polygons (textured polygons will overwrite)\n" -"\tif (fsTexParams.x < 0.5)\n" -"\t\tfragColor = gl_Color;\t\t\n" -"\telse\n" -"\t// Textured polygons: set fragment color to texel value\n" -"\t{\t\t\t\n" -"\t\t/*\n" -"\t\t * Bilinear Filtering\n" -"\t\t *\n" -"\t\t * In order to get this working on ATI, the number of operations is\n" -"\t\t * reduced by putting everything into vec4s. uv_top holds the UV \n" -"\t\t * coordinates for the top two texels (.xy=left, .zw=right) and uv_bot\n" -"\t\t * is for the lower two.\n" -"\t\t */\n" +"{ \n" +" vec4 uv_top, uv_bot, c[4];\n" +" vec2 r;\n" +" vec4 fragColor;\n" +" vec2 ellipse;\n" +" vec3 lightIntensity;\n" +" float insideSpot;\n" +" int x;\n" +" \n" +" // Get polygon color for untextured polygons (textured polygons will overwrite)\n" +" if (fsTexParams.x < 0.5)\n" +" fragColor = gl_Color; \n" +" else\n" +" // Textured polygons: set fragment color to texel value\n" +" { \n" +" /*\n" +" * Bilinear Filtering\n" +" *\n" +" * In order to get this working on ATI, the number of operations is\n" +" * reduced by putting everything into vec4s. uv_top holds the UV \n" +" * coordinates for the top two texels (.xy=left, .zw=right) and uv_bot\n" +" * is for the lower two.\n" +" */\n" "\n" -"\t\t// Compute fractional blending factor, r, and lower left corner of texel 0\n" -"\t\tuv_bot.xy = gl_TexCoord[0].st-vec2(0.5,0.5);\t// move into the lower left blending texel \n" -"\t\tr = uv_bot.xy-floor(uv_bot.xy);\t\t\t\t\t// fractional part\n" -"\t\tuv_bot.xy = floor(uv_bot.xy);\t\t\t\t\t// integral part\n" -"\t\t\n" -"\t\t// Compute texel coordinates\n" -"\t\tuv_bot.xy += vec2(0.5,0.5);\t// offset to center of pixel (should not be needed but it fixes a lot of glitches, esp. on Nvidia)\n" -"\t\tuv_bot.zw = uv_bot.xy + vec2(1.0,0.0);\t\t\t// compute coordinates of the other three neighbors\n" -"\t\tuv_top = uv_bot + vec4(0.0,1.0,0.0,1.0);\n" +" // Compute fractional blending factor, r, and lower left corner of texel 0\n" +" uv_bot.xy = gl_TexCoord[0].st-vec2(0.5,0.5); // move into the lower left blending texel\n" +" r = uv_bot.xy-floor(uv_bot.xy); // fractional part\n" +" uv_bot.xy = floor(uv_bot.xy); // integral part\n" +" \n" +" // Compute texel coordinates\n" +" uv_bot.xy += vec2(0.5,0.5); // offset to center of pixel (should not be needed but it fixes a lot of glitches, esp. on Nvidia)\n" +" uv_bot.zw = uv_bot.xy + vec2(1.0,0.0); // compute coordinates of the other three neighbors\n" +" uv_top = uv_bot + vec4(0.0,1.0,0.0,1.0);\n" "\n" -"\t\t// Compute the properly wrapped texel coordinates\n" -"\t\tuv_top = WrapTexelCoords(uv_top,vec4(fsSubTexture.xy,fsSubTexture.xy),vec4(fsSubTexture.zw,fsSubTexture.zw), vec4(fsTexParams.zw,fsTexParams.zw));\n" -"\t\tuv_bot = WrapTexelCoords(uv_bot,vec4(fsSubTexture.xy,fsSubTexture.xy),vec4(fsSubTexture.zw,fsSubTexture.zw), vec4(fsTexParams.zw,fsTexParams.zw));\n" +" // Compute the properly wrapped texel coordinates\n" +" uv_top = WrapTexelCoords(uv_top,vec4(fsSubTexture.xy,fsSubTexture.xy),vec4(fsSubTexture.zw,fsSubTexture.zw), vec4(fsTexParams.zw,fsTexParams.zw));\n" +" uv_bot = WrapTexelCoords(uv_bot,vec4(fsSubTexture.xy,fsSubTexture.xy),vec4(fsSubTexture.zw,fsSubTexture.zw), vec4(fsTexParams.zw,fsTexParams.zw));\n" "\n" -"\t\t// Fetch the texels\n" -"\t\tc[0]=texture2D(textureMap,uv_bot.xy);\t// bottom-left (base texel)\n" -"\t\tc[1]=texture2D(textureMap,uv_bot.zw);\t// bottom-right\n" -"\t\tc[2]=texture2D(textureMap,uv_top.xy);\t// top-left\n" -"\t\tc[3]=texture2D(textureMap,uv_top.zw);\t// top-right\t\t\n" +" // Fetch the texels\n" +" c[0]=texture2D(textureMap,uv_bot.xy); // bottom-left (base texel)\n" +" c[1]=texture2D(textureMap,uv_bot.zw); // bottom-right\n" +" c[2]=texture2D(textureMap,uv_top.xy); // top-left\n" +" c[3]=texture2D(textureMap,uv_top.zw); // top-right\n" "\n" -"\t\t// Interpolate texels and blend result with material color to determine final (unlit) fragment color\n" -"\t\t// fragColor = (c[0]*(1.0-r.s)*(1.0-r.t) + c[1]*r.s*(1.0-r.t) + c[2]*(1.0-r.s)*r.t + c[3]*r.s*r.t);\n" -"\t\t// Faster method:\n" -"\t\tc[0] += (c[1]-c[0])*r.s;\t\t\t// 2 alu\n" -"\t\tc[2] += (c[3]-c[2])*r.s;\t\t\t// 2 alu\n" -"\t\tfragColor = c[0]+(c[2]-c[0])*r.t;\t//2 alu\n" -"\t\n" -"\t\t/*\n" -"\t\t * T1RGB5:\n" -"\t\t *\n" -"\t\t * The transparency bit determines whether to discard pixels (if set).\n" -"\t\t * What is unknown is how this bit behaves when interpolated. OpenGL\n" -"\t\t * processes it as an alpha value, so it might concievably be blended\n" -"\t\t * with neighbors. Here, an arbitrary threshold is chosen.\n" -"\t\t *\n" -"\t\t * To-do: blending could probably enabled and this would work even\n" -"\t\t * better with a hard threshold.\n" -"\t\t *\n" -"\t\t * Countour processing also seems to be enabled for RGBA4 textures.\n" -"\t\t * When the alpha value is 0.0 (or close), pixels are discarded \n" -"\t\t * entirely.\n" -"\t\t */\n" -"\t\tif (fsTexParams.y > 0.5)\t// contour processing enabled\n" -"\t\t{\n" -"\t\t\tif (fragColor.a < 0.01)\t// discard anything with alpha == 0\n" -"\t\t\t\tdiscard;\n" -"\t\t}\n" -"\t\t\n" -"\t\t// If contour texture and not discarded, force alpha to 1.0 because will later be modified by polygon translucency\n" -"\t\tif (fsTexFormat < 0.5)\t\t// contour (T1RGB5) texture\n" -"\t\t\tfragColor.a = 1.0;\n" -"\t}\n" +" // Interpolate texels and blend result with material color to determine final (unlit) fragment color\n" +" // fragColor = (c[0]*(1.0-r.s)*(1.0-r.t) + c[1]*r.s*(1.0-r.t) + c[2]*(1.0-r.s)*r.t + c[3]*r.s*r.t);\n" +" // Faster method:\n" +" c[0] += (c[1]-c[0])*r.s; // 2 alu\n" +" c[2] += (c[3]-c[2])*r.s; // 2 alu\n" +" fragColor = c[0]+(c[2]-c[0])*r.t; //2 alu\n" "\n" -"\t// Compute spotlight and apply lighting\n" -"\tellipse = (gl_FragCoord.xy-spotEllipse.xy)/spotEllipse.zw;\n" -"\tinsideSpot = dot(ellipse,ellipse);\n" -"\tif ((insideSpot <= 1.0) && (fsViewZ>=spotRange.x) && (fsViewZ 0.5) // contour processing enabled\n" +" {\n" +" if (fragColor.a < 0.01) // discard anything with alpha == 0\n" +" discard;\n" +" }\n" +" \n" +" // If contour texture and not discarded, force alpha to 1.0 because will later be modified by polygon translucency\n" +" if (fsTexFormat < 0.5) // contour (T1RGB5) texture\n" +" fragColor.a = 1.0;\n" +" }\n" "\n" -"\t// Apply fog under the control of fog factor setting from polygon header\n" -"\tfragColor.rgb = mix(gl_Fog.color.rgb, fragColor.rgb, fsFogFactor);\n" +" // Compute spotlight and apply lighting\n" +" ellipse = (gl_FragCoord.xy-spotEllipse.xy)/spotEllipse.zw;\n" +" insideSpot = dot(ellipse,ellipse);\n" +" if ((insideSpot <= 1.0) && (fsViewZ>=spotRange.x) && (fsViewZ 0), .z=U wrap mode (1=mirror, 0=repeat), .w=V wrap mode\n" -"varying float\t\tfsTexFormat;\t// T1RGB5 contour texture (if > 0)\n" -"varying float\t\tfsTexMap;\t// texture map number\n" -"varying float\t\tfsTransLevel;\t// translucence level, 0.0 (transparent) to 1.0 (opaque)\n" -"varying vec3\t\tfsLightIntensity;\t// lighting intensity \n" -"varying float\t\tfsSpecularTerm;\t// specular highlight\n" -"varying float\t\tfsFogFactor;\t// fog factor\n" -"varying float\t\tfsViewZ;\t\t// Z distance to fragment from viewpoint at origin\n" +"varying vec4 fsSubTexture; // .x=texture X, .y=texture Y, .z=texture width, .w=texture height (all in texels)\n" +"varying vec4 fsTexParams; // .x=texture enable (if 1, else 0), .y=use transparency (if > 0), .z=U wrap mode (1=mirror, 0=repeat), .w=V wrap mode\n" +"varying float fsTexFormat; // T1RGB5 contour texture (if > 0)\n" +"varying float fsTexMap; // texture map number\n" +"varying float fsTransLevel; // translucence level, 0.0 (transparent) to 1.0 (opaque)\n" +"varying vec3 fsLightIntensity; // lighting intensity \n" +"varying float fsSpecularTerm; // specular highlight\n" +"varying float fsFogFactor; // fog factor\n" +"varying float fsViewZ; // Z distance to fragment from viewpoint at origin\n" "\n" "/*\n" " * WrapTexelCoords():\n" @@ -490,7 +518,7 @@ static const char fragmentShaderMultiSheetSource[] = " * X, Y position to select the appropriate one, and normalize by 2048\n" " * (the dimensions of the Real3D texture sheet).\n" " *\n" -" *\t\t= [(u,v)%(w,h)+(x,y)]/(2048,2048)\n" +" * = [(u,v)%(w,h)+(x,y)]/(2048,2048)\n" " *\n" " * If mirroring is enabled, textures are mirrored every odd multiple of\n" " * the original texture. To detect whether we are in an odd multiple, \n" @@ -498,8 +526,8 @@ static const char fragmentShaderMultiSheetSource[] = " * whether the result is odd. Then, clamp the coordinates as before but\n" " * subtract from the last texel to mirror them:\n" " *\n" -" * \t\t= [M*((w-1,h-1)-(u,v)%(w,h)) + (1-M)*(u,v)%(w,h) + (x,y)]/(2048,2048)\n" -" *\t\twhere M is 1.0 if the texture must be mirrored.\n" +" * = [M*((w-1,h-1)-(u,v)%(w,h)) + (1-M)*(u,v)%(w,h) + (x,y)]/(2048,2048)\n" +" * where M is 1.0 if the texture must be mirrored.\n" " *\n" " * As an optimization, this function computes TWO texture coordinates\n" " * simultaneously. The first is texCoord.xy, the second is in .zw. The other\n" @@ -507,16 +535,16 @@ static const char fragmentShaderMultiSheetSource[] = " */\n" "vec4 WrapTexelCoords(vec4 texCoord, vec4 texOffset, vec4 texSize, vec4 mirrorEnable)\n" "{\n" -"\tvec4\tclampedCoord, mirror, glTexCoord;\n" -"\t\n" -"\tclampedCoord = mod(texCoord,texSize);\t\t\t\t\t\t// clamp coordinates to within texture size\n" -"\tmirror = mirrorEnable * mod(floor(texCoord/texSize),2.0);\t// whether this texel needs to be mirrored\n" +" vec4 clampedCoord, mirror, glTexCoord;\n" +" \n" +" clampedCoord = mod(texCoord,texSize); // clamp coordinates to within texture size\n" +" mirror = mirrorEnable * mod(floor(texCoord/texSize),2.0); // whether this texel needs to be mirrored\n" "\n" -"\tglTexCoord = (\tmirror*(texSize-clampedCoord) +\n" -"\t\t\t\t\t(vec4(1.0,1.0,1.0,1.0)-mirror)*clampedCoord +\n" -"\t\t\t\t\ttexOffset\n" -"\t\t\t\t ) / mapSize;\n" -"\treturn glTexCoord;\n" +" glTexCoord = ( mirror*(texSize-clampedCoord) +\n" +" (vec4(1.0,1.0,1.0,1.0)-mirror)*clampedCoord +\n" +" texOffset\n" +" ) / mapSize;\n" +" return glTexCoord;\n" "}\n" "\n" "/*\n" @@ -526,138 +554,138 @@ static const char fragmentShaderMultiSheetSource[] = " */\n" "\n" "void main(void)\n" -"{\t\n" -"\tvec4\tuv_top, uv_bot, c[4];\n" -"\tvec2\tr;\n" -"\tvec4\tfragColor;\n" -"\tvec2\tellipse;\n" -"\tvec3\tlightIntensity;\n" -"\tfloat\tinsideSpot;\n" -"\tint\t\tx;\n" -"\t\n" -"\t// Get polygon color for untextured polygons (textured polygons will overwrite)\n" -"\tif (fsTexParams.x < 0.5)\n" -"\t\tfragColor = gl_Color;\t\t\n" -"\telse\n" -"\t// Textured polygons: set fragment color to texel value\n" -"\t{\t\t\t\n" -"\t\t/*\n" -"\t\t * Bilinear Filtering\n" -"\t\t *\n" -"\t\t * In order to get this working on ATI, the number of operations is\n" -"\t\t * reduced by putting everything into vec4s. uv_top holds the UV \n" -"\t\t * coordinates for the top two texels (.xy=left, .zw=right) and uv_bot\n" -"\t\t * is for the lower two.\n" -"\t\t */\n" +"{ \n" +" vec4 uv_top, uv_bot, c[4];\n" +" vec2 r;\n" +" vec4 fragColor;\n" +" vec2 ellipse;\n" +" vec3 lightIntensity;\n" +" float insideSpot;\n" +" int x;\n" +" \n" +" // Get polygon color for untextured polygons (textured polygons will overwrite)\n" +" if (fsTexParams.x < 0.5)\n" +" fragColor = gl_Color; \n" +" else\n" +" // Textured polygons: set fragment color to texel value\n" +" { \n" +" /*\n" +" * Bilinear Filtering\n" +" *\n" +" * In order to get this working on ATI, the number of operations is\n" +" * reduced by putting everything into vec4s. uv_top holds the UV \n" +" * coordinates for the top two texels (.xy=left, .zw=right) and uv_bot\n" +" * is for the lower two.\n" +" */\n" "\n" -"\t\t// Compute fractional blending factor, r, and lower left corner of texel 0\n" -"\t\tuv_bot.xy = gl_TexCoord[0].st-vec2(0.5,0.5);\t// move into the lower left blending texel \n" -"\t\tr = uv_bot.xy-floor(uv_bot.xy);\t\t\t\t\t// fractional part\n" -"\t\tuv_bot.xy = floor(uv_bot.xy);\t\t\t\t\t// integral part\n" -"\t\t\n" -"\t\t// Compute texel coordinates\n" -"\t\tuv_bot.xy += vec2(0.5,0.5);\t// offset to center of pixel (should not be needed but it fixes a lot of glitches, esp. on Nvidia)\n" -"\t\tuv_bot.zw = uv_bot.xy + vec2(1.0,0.0);\t\t\t// compute coordinates of the other three neighbors\n" -"\t\tuv_top = uv_bot + vec4(0.0,1.0,0.0,1.0);\n" +" // Compute fractional blending factor, r, and lower left corner of texel 0\n" +" uv_bot.xy = gl_TexCoord[0].st-vec2(0.5,0.5); // move into the lower left blending texel \n" +" r = uv_bot.xy-floor(uv_bot.xy); // fractional part\n" +" uv_bot.xy = floor(uv_bot.xy); // integral part\n" +" \n" +" // Compute texel coordinates\n" +" uv_bot.xy += vec2(0.5,0.5); // offset to center of pixel (should not be needed but it fixes a lot of glitches, esp. on Nvidia)\n" +" uv_bot.zw = uv_bot.xy + vec2(1.0,0.0); // compute coordinates of the other three neighbors\n" +" uv_top = uv_bot + vec4(0.0,1.0,0.0,1.0);\n" "\n" -"\t\t// Compute the properly wrapped texel coordinates\n" -"\t\tuv_top = WrapTexelCoords(uv_top,vec4(fsSubTexture.xy,fsSubTexture.xy),vec4(fsSubTexture.zw,fsSubTexture.zw), vec4(fsTexParams.zw,fsTexParams.zw));\n" -"\t\tuv_bot = WrapTexelCoords(uv_bot,vec4(fsSubTexture.xy,fsSubTexture.xy),vec4(fsSubTexture.zw,fsSubTexture.zw), vec4(fsTexParams.zw,fsTexParams.zw));\n" +" // Compute the properly wrapped texel coordinates\n" +" uv_top = WrapTexelCoords(uv_top,vec4(fsSubTexture.xy,fsSubTexture.xy),vec4(fsSubTexture.zw,fsSubTexture.zw), vec4(fsTexParams.zw,fsTexParams.zw));\n" +" uv_bot = WrapTexelCoords(uv_bot,vec4(fsSubTexture.xy,fsSubTexture.xy),vec4(fsSubTexture.zw,fsSubTexture.zw), vec4(fsTexParams.zw,fsTexParams.zw));\n" "\n" -"\t\t// Fetch the texels from the given texture map\n" -"\t\tif (fsTexMap < 0.5f)\t{\n" -"\t\t\tc[0]=texture2D(textureMap0, uv_bot.xy); // bottom-left (base texel)\n" -"\t\t\tc[1]=texture2D(textureMap0, uv_bot.zw); // bottom-right\n" -"\t\t\tc[2]=texture2D(textureMap0, uv_top.xy); // top-left\n" -"\t\t\tc[3]=texture2D(textureMap0, uv_top.zw); // top-right\n" -"\t\t} else if (fsTexMap < 1.5f) {\n" -" c[0]=texture2D(textureMap1, uv_bot.xy); // bottom-left (base texel)\n" -"\t\t\tc[1]=texture2D(textureMap1, uv_bot.zw); // bottom-right\n" -"\t\t\tc[2]=texture2D(textureMap1, uv_top.xy); // top-left\n" -"\t\t\tc[3]=texture2D(textureMap1, uv_top.zw); // top-right\n" -"\t\t} else if (fsTexMap < 2.5f) {\n" -" c[0]=texture2D(textureMap2, uv_bot.xy); // bottom-left (base texel)\n" -"\t\t\tc[1]=texture2D(textureMap2, uv_bot.zw); // bottom-right\n" -"\t\t\tc[2]=texture2D(textureMap2, uv_top.xy); // top-left\n" -"\t\t\tc[3]=texture2D(textureMap2, uv_top.zw); // top-right\n" -"\t\t} else if (fsTexMap < 3.5f) {\n" -" c[0]=texture2D(textureMap3, uv_bot.xy); // bottom-left (base texel)\n" -"\t\t\tc[1]=texture2D(textureMap3, uv_bot.zw); // bottom-right\n" -"\t\t\tc[2]=texture2D(textureMap3, uv_top.xy); // top-left\n" -"\t\t\tc[3]=texture2D(textureMap3, uv_top.zw); // top-right\n" -"\t\t} else if (fsTexMap < 4.5f) {\n" -" c[0]=texture2D(textureMap4, uv_bot.xy); // bottom-left (base texel)\n" -"\t\t\tc[1]=texture2D(textureMap4, uv_bot.zw); // bottom-right\n" -"\t\t\tc[2]=texture2D(textureMap4, uv_top.xy); // top-left\n" -"\t\t\tc[3]=texture2D(textureMap4, uv_top.zw); // top-right\n" -"\t\t} else if (fsTexMap < 5.5f) {\n" -" c[0]=texture2D(textureMap5, uv_bot.xy); // bottom-left (base texel)\n" -"\t\t\tc[1]=texture2D(textureMap5, uv_bot.zw); // bottom-right\n" -"\t\t\tc[2]=texture2D(textureMap5, uv_top.xy); // top-left\n" -"\t\t\tc[3]=texture2D(textureMap5, uv_top.zw); // top-right\n" -"\t\t} else if (fsTexMap < 6.5f) {\n" -"\t\t\tc[0]=texture2D(textureMap6, uv_bot.xy); // bottom-left (base texel)\n" -"\t\t\tc[1]=texture2D(textureMap6, uv_bot.zw); // bottom-right\n" -"\t\t\tc[2]=texture2D(textureMap6, uv_top.xy); // top-left\n" -"\t\t\tc[3]=texture2D(textureMap6, uv_top.zw); // top-right\n" -"\t\t} else {\n" -" c[0]=texture2D(textureMap7, uv_bot.xy); // bottom-left (base texel)\n" -"\t\t\tc[1]=texture2D(textureMap7, uv_bot.zw); // bottom-right\n" -"\t\t\tc[2]=texture2D(textureMap7, uv_top.xy); // top-left\n" -"\t\t\tc[3]=texture2D(textureMap7, uv_top.zw); // top-right\n" -"\t\t} \n" +" // Fetch the texels from the given texture map\n" +" if (fsTexMap < 0.5f) {\n" +" c[0]=texture2D(textureMap0, uv_bot.xy); // bottom-left (base texel)\n" +" c[1]=texture2D(textureMap0, uv_bot.zw); // bottom-right\n" +" c[2]=texture2D(textureMap0, uv_top.xy); // top-left\n" +" c[3]=texture2D(textureMap0, uv_top.zw); // top-right\n" +" } else if (fsTexMap < 1.5f) {\n" +" c[0]=texture2D(textureMap1, uv_bot.xy); // bottom-left (base texel)\n" +" c[1]=texture2D(textureMap1, uv_bot.zw); // bottom-right\n" +" c[2]=texture2D(textureMap1, uv_top.xy); // top-left\n" +" c[3]=texture2D(textureMap1, uv_top.zw); // top-right\n" +" } else if (fsTexMap < 2.5f) {\n" +" c[0]=texture2D(textureMap2, uv_bot.xy); // bottom-left (base texel)\n" +" c[1]=texture2D(textureMap2, uv_bot.zw); // bottom-right\n" +" c[2]=texture2D(textureMap2, uv_top.xy); // top-left\n" +" c[3]=texture2D(textureMap2, uv_top.zw); // top-right\n" +" } else if (fsTexMap < 3.5f) {\n" +" c[0]=texture2D(textureMap3, uv_bot.xy); // bottom-left (base texel)\n" +" c[1]=texture2D(textureMap3, uv_bot.zw); // bottom-right\n" +" c[2]=texture2D(textureMap3, uv_top.xy); // top-left\n" +" c[3]=texture2D(textureMap3, uv_top.zw); // top-right\n" +" } else if (fsTexMap < 4.5f) {\n" +" c[0]=texture2D(textureMap4, uv_bot.xy); // bottom-left (base texel)\n" +" c[1]=texture2D(textureMap4, uv_bot.zw); // bottom-right\n" +" c[2]=texture2D(textureMap4, uv_top.xy); // top-left\n" +" c[3]=texture2D(textureMap4, uv_top.zw); // top-right\n" +" } else if (fsTexMap < 5.5f) {\n" +" c[0]=texture2D(textureMap5, uv_bot.xy); // bottom-left (base texel)\n" +" c[1]=texture2D(textureMap5, uv_bot.zw); // bottom-right\n" +" c[2]=texture2D(textureMap5, uv_top.xy); // top-left\n" +" c[3]=texture2D(textureMap5, uv_top.zw); // top-right\n" +" } else if (fsTexMap < 6.5f) {\n" +" c[0]=texture2D(textureMap6, uv_bot.xy); // bottom-left (base texel)\n" +" c[1]=texture2D(textureMap6, uv_bot.zw); // bottom-right\n" +" c[2]=texture2D(textureMap6, uv_top.xy); // top-left\n" +" c[3]=texture2D(textureMap6, uv_top.zw); // top-right\n" +" } else {\n" +" c[0]=texture2D(textureMap7, uv_bot.xy); // bottom-left (base texel)\n" +" c[1]=texture2D(textureMap7, uv_bot.zw); // bottom-right\n" +" c[2]=texture2D(textureMap7, uv_top.xy); // top-left\n" +" c[3]=texture2D(textureMap7, uv_top.zw); // top-right\n" +" } \n" "\n" -"\t\t// Interpolate texels and blend result with material color to determine final (unlit) fragment color\n" -"\t\t// fragColor = (c[0]*(1.0-r.s)*(1.0-r.t) + c[1]*r.s*(1.0-r.t) + c[2]*(1.0-r.s)*r.t + c[3]*r.s*r.t);\n" -"\t\t// Faster method:\n" -"\t\tc[0] += (c[1]-c[0])*r.s;\t\t\t// 2 alu\n" -"\t\tc[2] += (c[3]-c[2])*r.s;\t\t\t// 2 alu\n" -"\t\tfragColor = c[0]+(c[2]-c[0])*r.t;\t// 2 alu\n" -"\t\n" -"\t\t/*\n" -"\t\t * T1RGB5:\n" -"\t\t *\n" -"\t\t * The transparency bit determines whether to discard pixels (if set).\n" -"\t\t * What is unknown is how this bit behaves when interpolated. OpenGL\n" -"\t\t * processes it as an alpha value, so it might concievably be blended\n" -"\t\t * with neighbors. Here, an arbitrary threshold is chosen.\n" -"\t\t *\n" -"\t\t * To-do: blending could probably enabled and this would work even\n" -"\t\t * better with a hard threshold.\n" -"\t\t *\n" -"\t\t * Countour processing also seems to be enabled for RGBA4 textures.\n" -"\t\t * When the alpha value is 0.0 (or close), pixels are discarded \n" -"\t\t * entirely.\n" -"\t\t */\n" -"\t\tif (fsTexParams.y > 0.5)\t// contour processing enabled\n" -"\t\t{\n" -"\t\t\tif (fragColor.a < 0.01)\t// discard anything with alpha == 0\n" -"\t\t\t\tdiscard;\n" -"\t\t}\n" -"\t\t\n" -"\t\t// If contour texture and not discarded, force alpha to 1.0 because will later be modified by polygon translucency\n" -"\t\tif (fsTexFormat < 0.5)\t\t// contour (T1RGB5) texture map\n" -"\t\t\tfragColor.a = 1.0;\n" -"\t}\n" +" // Interpolate texels and blend result with material color to determine final (unlit) fragment color\n" +" // fragColor = (c[0]*(1.0-r.s)*(1.0-r.t) + c[1]*r.s*(1.0-r.t) + c[2]*(1.0-r.s)*r.t + c[3]*r.s*r.t);\n" +" // Faster method:\n" +" c[0] += (c[1]-c[0])*r.s; // 2 alu\n" +" c[2] += (c[3]-c[2])*r.s; // 2 alu\n" +" fragColor = c[0]+(c[2]-c[0])*r.t; // 2 alu\n" "\n" -"\t// Compute spotlight and apply lighting\n" -"\tellipse = (gl_FragCoord.xy-spotEllipse.xy)/spotEllipse.zw;\n" -"\tinsideSpot = dot(ellipse,ellipse);\n" -"\tif ((insideSpot <= 1.0) && (fsViewZ>=spotRange.x) && (fsViewZ 0.5) // contour processing enabled\n" +" {\n" +" if (fragColor.a < 0.01) // discard anything with alpha == 0\n" +" discard;\n" +" }\n" +" \n" +" // If contour texture and not discarded, force alpha to 1.0 because will later be modified by polygon translucency\n" +" if (fsTexFormat < 0.5) // contour (T1RGB5) texture map\n" +" fragColor.a = 1.0;\n" +" }\n" "\n" -"\t// Apply fog under the control of fog factor setting from polygon header\n" -"\tfragColor.rgb = mix(gl_Fog.color.rgb, fragColor.rgb, fsFogFactor);\n" +" // Compute spotlight and apply lighting\n" +" ellipse = (gl_FragCoord.xy-spotEllipse.xy)/spotEllipse.zw;\n" +" insideSpot = dot(ellipse,ellipse);\n" +" if ((insideSpot <= 1.0) && (fsViewZ>=spotRange.x) && (fsViewZ