mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-03-17 08:21:28 +00:00
Merge branch 'master' of https://github.com/coelckers/gzdoom
# Conflicts: # src/textures/hires/hqresize.cpp # wadsrc/static/language.enu # wadsrc/static/menudef.txt # wadsrc/static/zscript/menu/optionmenu.txt
This commit is contained in:
commit
555d1100df
8 changed files with 113 additions and 41 deletions
|
@ -129,7 +129,7 @@ void FUE1Model::LoadGeometry()
|
|||
FVector3 dir[2];
|
||||
dir[0] = verts[Poly.V[1]+numVerts*j].Pos-verts[Poly.V[0]+numVerts*j].Pos;
|
||||
dir[1] = verts[Poly.V[2]+numVerts*j].Pos-verts[Poly.V[0]+numVerts*j].Pos;
|
||||
Poly.Normals.Push(dir[0]^dir[1]);
|
||||
Poly.Normals.Push((dir[0]^dir[1]).Unit());
|
||||
}
|
||||
// push
|
||||
polys.Push(Poly);
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
CUSTOM_CVAR(Int, gl_texture_hqresize, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||
{
|
||||
if (self < 0 || self > 22)
|
||||
if (self < 0 || self > 24)
|
||||
{
|
||||
self = 0;
|
||||
}
|
||||
|
@ -439,6 +439,10 @@ unsigned char *FTexture::CreateUpsampledTextureBuffer (unsigned char *inputBuffe
|
|||
return normalNxHelper( &normalNx, 3, inputBuffer, inWidth, inHeight, outWidth, outHeight );
|
||||
case 22:
|
||||
return normalNxHelper( &normalNx, 4, inputBuffer, inWidth, inHeight, outWidth, outHeight );
|
||||
case 23:
|
||||
return normalNxHelper( &normalNx, 5, inputBuffer, inWidth, inHeight, outWidth, outHeight );
|
||||
case 24:
|
||||
return normalNxHelper( &normalNx, 6, inputBuffer, inWidth, inHeight, outWidth, outHeight );
|
||||
}
|
||||
}
|
||||
return inputBuffer;
|
||||
|
|
|
@ -2441,6 +2441,8 @@ OPTVAL_SOUNDSYSTEM = "Sound System";
|
|||
OPTVAL_FOO_DUMB = "foo_dumb";
|
||||
OPTVAL_ALIASING = "Aliasing";
|
||||
OPTVAL_LINEAR = "Linear";
|
||||
OPTVAL_NEAREST = "Nearest";
|
||||
OPTVAL_PCF = "PCF";
|
||||
OPTVAL_CUBIC = "Cubic";
|
||||
OPTVAL_BLEP = "Band-limited step";
|
||||
OPTVAL_LINEARSLOW = "Linear (Slower)";
|
||||
|
@ -2879,6 +2881,8 @@ OPTVAL_SCALE4X = "Scale4x";
|
|||
OPTVAL_NORMAL2X = "Normal2x";
|
||||
OPTVAL_NORMAL3X = "Normal3x";
|
||||
OPTVAL_NORMAL4X = "Normal4x";
|
||||
OPTVAL_NORMAL5X = "Normal5x";
|
||||
OPTVAL_NORMAL6X = "Normal6x";
|
||||
OPTVAL_HQ2X = "hq2x";
|
||||
OPTVAL_HQ3X = "hq3x";
|
||||
OPTVAL_HQ4X = "hq4x";
|
||||
|
|
|
@ -2418,6 +2418,8 @@ OPTVAL_OLD = "Ancien";
|
|||
OPTVAL_DEFAULT = "Défaut";
|
||||
OPTVAL_SOUNDSYSTEM = "Système Sonore";
|
||||
OPTVAL_LINEAR = "Linéaire";
|
||||
OPTVAL_NEAREST = "Nearest";
|
||||
OPTVAL_PCF = "PCF";
|
||||
OPTVAL_CUBIC = "Cubique";
|
||||
OPTVAL_BLEP = "Step limité sur bande";
|
||||
OPTVAL_LINEARSLOW = "Linéaire (Lent)";
|
||||
|
|
|
@ -2188,6 +2188,8 @@ OptionValue "HqResizeModes"
|
|||
20, "$OPTVAL_NORMAL2X"
|
||||
21, "$OPTVAL_NORMAL3X"
|
||||
22, "$OPTVAL_NORMAL4X"
|
||||
23, "$OPTVAL_NORMAL5X"
|
||||
24, "$OPTVAL_NORMAL6X"
|
||||
}
|
||||
|
||||
OptionValue "HqResizeModesNoMMX"
|
||||
|
@ -2258,8 +2260,8 @@ OptionValue ShadowMapQuality
|
|||
|
||||
OptionValue ShadowMapFilter
|
||||
{
|
||||
0, "$OPTVAL_LINEAR"
|
||||
1, "PCF"
|
||||
0, "$OPTVAL_NEAREST"
|
||||
1, "$OPTVAL_PCF"
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -160,19 +160,21 @@ float R_DoomLightingEquation(float light)
|
|||
|
||||
float shadowDirToU(vec2 dir)
|
||||
{
|
||||
if (abs(dir.x) > abs(dir.y))
|
||||
if (abs(dir.y) > abs(dir.x))
|
||||
{
|
||||
if (dir.x >= 0.0)
|
||||
return dir.y / dir.x * 0.125 + (0.25 + 0.125);
|
||||
float x = dir.x / dir.y * 0.125;
|
||||
if (dir.y >= 0.0)
|
||||
return 0.125 + x;
|
||||
else
|
||||
return dir.y / dir.x * 0.125 + (0.75 + 0.125);
|
||||
return (0.50 + 0.125) + x;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dir.y >= 0.0)
|
||||
return dir.x / dir.y * 0.125 + 0.125;
|
||||
float y = dir.y / dir.x * 0.125;
|
||||
if (dir.x >= 0.0)
|
||||
return (0.25 + 0.125) - y;
|
||||
else
|
||||
return dir.x / dir.y * 0.125 + (0.50 + 0.125);
|
||||
return (0.75 + 0.125) - y;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,7 +182,7 @@ float sampleShadowmap(vec2 dir, float v)
|
|||
{
|
||||
float u = shadowDirToU(dir);
|
||||
float dist2 = dot(dir, dir);
|
||||
return texture(ShadowMap, vec2(u, v)).x > dist2 ? 1.0 : 0.0;
|
||||
return step(dist2, texture(ShadowMap, vec2(u, v)).x);
|
||||
}
|
||||
|
||||
float sampleShadowmapLinear(vec2 dir, float v)
|
||||
|
@ -209,6 +211,40 @@ float sampleShadowmapLinear(vec2 dir, float v)
|
|||
return mix(step(dist2, depth0), step(dist2, depth1), t);
|
||||
}
|
||||
|
||||
vec2 shadowmapAdjustedRay(vec4 lightpos)
|
||||
{
|
||||
vec3 planePoint = pixelpos.xyz - lightpos.xyz;
|
||||
|
||||
if (dot(planePoint.xz, planePoint.xz) < 1.0)
|
||||
return planePoint.xz * 0.5;
|
||||
|
||||
vec3 ray = normalize(planePoint);
|
||||
|
||||
vec2 isize = textureSize(ShadowMap, 0);
|
||||
float scale = float(isize.x) * 0.25;
|
||||
|
||||
// Snap to shadow map texel grid
|
||||
if (abs(ray.z) > abs(ray.x))
|
||||
{
|
||||
ray.y = ray.y / abs(ray.z);
|
||||
ray.x = ray.x / abs(ray.z);
|
||||
ray.x = (floor((ray.x + 1.0) * 0.5 * scale) + 0.5) / scale * 2.0 - 1.0;
|
||||
ray.z = sign(ray.z);
|
||||
}
|
||||
else
|
||||
{
|
||||
ray.y = ray.y / abs(ray.x);
|
||||
ray.z = ray.z / abs(ray.x);
|
||||
ray.z = (floor((ray.z + 1.0) * 0.5 * scale) + 0.5) / scale * 2.0 - 1.0;
|
||||
ray.x = sign(ray.x);
|
||||
}
|
||||
|
||||
float bias = 1.0;
|
||||
float negD = dot(vWorldNormal.xyz, planePoint);
|
||||
float t = negD / dot(vWorldNormal.xyz, ray) - bias;
|
||||
return ray.xz * t;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Check if light is in shadow using Percentage Closer Filtering (PCF)
|
||||
|
@ -222,22 +258,20 @@ float shadowmapAttenuation(vec4 lightpos, float shadowIndex)
|
|||
|
||||
float v = (shadowIndex + 0.5) / 1024.0;
|
||||
|
||||
vec2 ray = pixelpos.xz - lightpos.xz;
|
||||
float length = length(ray);
|
||||
if (length < 3.0)
|
||||
return 1.0;
|
||||
|
||||
vec2 dir = ray / length;
|
||||
vec2 ray = shadowmapAdjustedRay(lightpos);
|
||||
|
||||
if (uShadowmapFilter <= 0)
|
||||
{
|
||||
ray -= dir * 2.0; // Shadow acne margin
|
||||
return sampleShadowmapLinear(ray, v);
|
||||
return sampleShadowmap(ray, v);
|
||||
//return sampleShadowmapLinear(ray, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
ray -= dir * 2.0; // Shadow acne margin
|
||||
dir = dir * min(length / 50.0, 1.0); // avoid sampling behind light
|
||||
float length = length(ray);
|
||||
if (length < 3.0)
|
||||
return 1.0;
|
||||
|
||||
vec2 dir = ray / length * min(length / 50.0, 1.0); // avoid sampling behind light
|
||||
|
||||
vec2 normal = vec2(-dir.y, dir.x);
|
||||
vec2 bias = dir * 10.0;
|
||||
|
@ -251,10 +285,6 @@ float shadowmapAttenuation(vec4 lightpos, float shadowIndex)
|
|||
}
|
||||
return sum / uShadowmapFilter;
|
||||
}
|
||||
#if 0 // nearest shadow filter (not used)
|
||||
ray -= dir * 6.0; // Shadow acne margin
|
||||
return sampleShadowmap(ray, v);
|
||||
#endif
|
||||
}
|
||||
|
||||
float shadowAttenuation(vec4 lightpos, float lightcolorA)
|
||||
|
|
|
@ -2,20 +2,22 @@
|
|||
in vec2 TexCoord;
|
||||
layout(location=0) out vec4 FragColor;
|
||||
|
||||
// A node in an AABB binary tree with lines stored in the leaf nodes
|
||||
struct GPUNode
|
||||
{
|
||||
vec2 aabb_min;
|
||||
vec2 aabb_max;
|
||||
int left;
|
||||
int right;
|
||||
int line_index;
|
||||
int padding;
|
||||
vec2 aabb_min; // Min xy values for the axis-aligned box containing the node and its subtree
|
||||
vec2 aabb_max; // Max xy values
|
||||
int left; // Left subnode index
|
||||
int right; // Right subnode index
|
||||
int line_index; // Line index if it is a leaf node, otherwise -1
|
||||
int padding; // Unused - maintains 16 byte alignment
|
||||
};
|
||||
|
||||
// 2D line segment, referenced by leaf nodes
|
||||
struct GPULine
|
||||
{
|
||||
vec2 pos;
|
||||
vec2 delta;
|
||||
vec2 pos; // Line start position
|
||||
vec2 delta; // Line end position - line start position
|
||||
};
|
||||
|
||||
layout(std430, binding = 2) buffer LightNodes
|
||||
|
@ -33,6 +35,7 @@ layout(std430, binding = 4) buffer LightList
|
|||
vec4 lights[];
|
||||
};
|
||||
|
||||
// Overlap test between line segment and axis-aligned bounding box. Returns true if they overlap.
|
||||
bool overlapRayAABB(vec2 ray_start2d, vec2 ray_end2d, vec2 aabb_min2d, vec2 aabb_max2d)
|
||||
{
|
||||
// To do: simplify test to use a 2D test
|
||||
|
@ -60,6 +63,8 @@ bool overlapRayAABB(vec2 ray_start2d, vec2 ray_end2d, vec2 aabb_min2d, vec2 aabb
|
|||
return true; // overlap;
|
||||
}
|
||||
|
||||
// Intersection test between two line segments.
|
||||
// Returns the intersection point as a value between 0-1 on the ray line segment. 1.0 if there was no hit.
|
||||
float intersectRayLine(vec2 ray_start, vec2 ray_end, int line_index, vec2 raydelta, float rayd, float raydist2)
|
||||
{
|
||||
const float epsilon = 0.0000001;
|
||||
|
@ -82,11 +87,14 @@ float intersectRayLine(vec2 ray_start, vec2 ray_end, int line_index, vec2 raydel
|
|||
return 1.0;
|
||||
}
|
||||
|
||||
// Returns true if an AABB tree node is a leaf node. Leaf nodes contains a line.
|
||||
bool isLeaf(int node_index)
|
||||
{
|
||||
return nodes[node_index].line_index != -1;
|
||||
}
|
||||
|
||||
// Perform ray intersection test between the ray line segment and all the lines in the AABB binary tree.
|
||||
// Returns the intersection point as a value between 0-1 on the ray line segment. 1.0 if there was no hit.
|
||||
float rayTest(vec2 ray_start, vec2 ray_end)
|
||||
{
|
||||
vec2 raydelta = ray_end - ray_start;
|
||||
|
@ -98,6 +106,9 @@ float rayTest(vec2 ray_start, vec2 ray_end)
|
|||
|
||||
float t = 1.0;
|
||||
|
||||
// Walk the AABB binary tree searching for nodes touching the ray line segment's AABB box.
|
||||
// When it reaches a leaf node, use a line segment intersection test to see if we got a hit.
|
||||
|
||||
int stack[16];
|
||||
int stack_pos = 1;
|
||||
stack[0] = nodes.length() - 1;
|
||||
|
@ -131,6 +142,8 @@ float rayTest(vec2 ray_start, vec2 ray_end)
|
|||
|
||||
void main()
|
||||
{
|
||||
// Find the light that belongs to this texel in the shadowmap texture we output to:
|
||||
|
||||
int lightIndex = int(gl_FragCoord.y);
|
||||
|
||||
vec4 light = lights[lightIndex];
|
||||
|
@ -139,17 +152,32 @@ void main()
|
|||
|
||||
if (radius > 0.0)
|
||||
{
|
||||
vec2 pixelpos;
|
||||
switch (int(gl_FragCoord.x) / int(ShadowmapQuality/4.0))
|
||||
// We found an active light. Calculate the ray direction for the texel.
|
||||
//
|
||||
// The texels are laid out so that there are four projections:
|
||||
//
|
||||
// * top-left to top-right
|
||||
// * top-right to bottom-right
|
||||
// * bottom-right to bottom-left
|
||||
// * bottom-left to top-left
|
||||
//
|
||||
vec2 raydir;
|
||||
float u = gl_FragCoord.x / ShadowmapQuality * 4.0;
|
||||
switch (int(u))
|
||||
{
|
||||
case 0: pixelpos = vec2((gl_FragCoord.x - float(ShadowmapQuality/8.0)) / float(ShadowmapQuality/8.0), 1.0); break;
|
||||
case 1: pixelpos = vec2(1.0, (gl_FragCoord.x - float(ShadowmapQuality/4.0 + ShadowmapQuality/8.0)) / float(ShadowmapQuality/8.0)); break;
|
||||
case 2: pixelpos = vec2(-(gl_FragCoord.x - float(ShadowmapQuality/2.0 + ShadowmapQuality/8.0)) / float(ShadowmapQuality/8.0), -1.0); break;
|
||||
case 3: pixelpos = vec2(-1.0, -(gl_FragCoord.x - float(ShadowmapQuality*3.0/4.0 + ShadowmapQuality/8.0)) / float(ShadowmapQuality/8.0)); break;
|
||||
case 0: raydir = vec2(u * 2.0 - 1.0, 1.0); break;
|
||||
case 1: raydir = vec2(1.0, 1.0 - (u - 1.0) * 2.0); break;
|
||||
case 2: raydir = vec2(1.0 - (u - 2.0) * 2.0, -1.0); break;
|
||||
case 3: raydir = vec2(-1.0, (u - 3.0) * 2.0 - 1.0); break;
|
||||
}
|
||||
pixelpos = lightpos + pixelpos * radius;
|
||||
|
||||
// Find the position for the ray starting at the light position and travelling until light contribution is zero:
|
||||
vec2 pixelpos = lightpos + raydir * radius;
|
||||
|
||||
// Check if we hit any line between the light and the end position:
|
||||
float t = rayTest(lightpos, pixelpos);
|
||||
|
||||
// Calculate the square distance for the hit, if any:
|
||||
vec2 delta = (pixelpos - lightpos) * t;
|
||||
float dist2 = dot(delta, delta);
|
||||
|
||||
|
|
|
@ -595,10 +595,12 @@ class GLTextureGLOptions : OptionMenu
|
|||
break;
|
||||
case 16:
|
||||
case 18:
|
||||
case 23:
|
||||
multiplier = 25;
|
||||
break;
|
||||
case 17:
|
||||
case 19:
|
||||
case 24:
|
||||
multiplier = 36;
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue