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
This commit is contained in:
commit
b147d18b36
11 changed files with 265 additions and 124 deletions
|
@ -16,7 +16,7 @@ matrix:
|
|||
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
osx_image: xcode10
|
||||
env:
|
||||
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9"
|
||||
|
||||
|
|
|
@ -48,5 +48,7 @@
|
|||
<string>NSApplication</string>
|
||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||
<true/>
|
||||
<key>NSRequiresAquaSystemAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -101,8 +101,9 @@ bool FOBJModel::Load(const char* fn, int lumpnum, const char* buffer, int length
|
|||
|
||||
FTextureID curMtl = FNullTextureID();
|
||||
OBJSurface *curSurface = nullptr;
|
||||
int aggSurfFaceCount = 0;
|
||||
int curSurfFaceCount = 0;
|
||||
unsigned int aggSurfFaceCount = 0;
|
||||
unsigned int curSurfFaceCount = 0;
|
||||
unsigned int curSmoothGroup = 0;
|
||||
|
||||
while(sc.GetString())
|
||||
{
|
||||
|
@ -186,9 +187,25 @@ bool FOBJModel::Load(const char* fn, int lumpnum, const char* buffer, int length
|
|||
sc.UnGet(); // No 4th side, move back
|
||||
}
|
||||
}
|
||||
face.smoothGroup = curSmoothGroup;
|
||||
faces.Push(face);
|
||||
curSurfFaceCount += 1;
|
||||
}
|
||||
else if (sc.Compare("s"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("off"))
|
||||
{
|
||||
curSmoothGroup = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.UnGet();
|
||||
sc.MustGetNumber();
|
||||
curSmoothGroup = sc.Number;
|
||||
hasSmoothGroups = hasSmoothGroups || curSmoothGroup > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
sc.Close();
|
||||
|
||||
|
@ -277,11 +294,13 @@ bool FOBJModel::ParseFaceSide(const FString &sideStr, OBJFace &face, int sidx)
|
|||
else
|
||||
{
|
||||
side.normref = -1;
|
||||
hasMissingNormals = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
side.normref = -1;
|
||||
hasMissingNormals = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -289,6 +308,7 @@ bool FOBJModel::ParseFaceSide(const FString &sideStr, OBJFace &face, int sidx)
|
|||
origIdx = atoi(sideStr.GetChars());
|
||||
side.vertref = ResolveIndex(origIdx, FaceElement::VertexIndex);
|
||||
side.normref = -1;
|
||||
hasMissingNormals = true;
|
||||
side.uvref = -1;
|
||||
}
|
||||
face.sides[sidx] = side;
|
||||
|
@ -348,15 +368,20 @@ void FOBJModel::BuildVertexBuffer(FModelRenderer *renderer)
|
|||
surfaces[i].vbStart = vbufsize;
|
||||
vbufsize += surfaces[i].numTris * 3;
|
||||
}
|
||||
// Initialize/populate vertFaces
|
||||
if (hasMissingNormals && hasSmoothGroups)
|
||||
{
|
||||
AddVertFaces();
|
||||
}
|
||||
|
||||
auto vbuf = renderer->CreateVertexBuffer(false,true);
|
||||
SetVertexBuffer(renderer, vbuf);
|
||||
|
||||
FModelVertex *vertptr = vbuf->LockVertexBuffer(vbufsize);
|
||||
|
||||
for (size_t i = 0; i < surfaces.Size(); i++)
|
||||
for (unsigned int i = 0; i < surfaces.Size(); i++)
|
||||
{
|
||||
for (size_t j = 0; j < surfaces[i].numTris; j++)
|
||||
for (unsigned int j = 0; j < surfaces[i].numTris; j++)
|
||||
{
|
||||
for (size_t side = 0; side < 3; side++)
|
||||
{
|
||||
|
@ -372,39 +397,40 @@ void FOBJModel::BuildVertexBuffer(FModelRenderer *renderer)
|
|||
|
||||
FVector3 curVvec = RealignVector(verts[vidx]);
|
||||
FVector2 curUvec = FixUV(uvs[uvidx]);
|
||||
FVector3 *nvec = nullptr;
|
||||
FVector3 nvec;
|
||||
|
||||
mdv->Set(curVvec.X, curVvec.Y, curVvec.Z, curUvec.X, curUvec.Y);
|
||||
|
||||
if (nidx >= 0 && (unsigned int)nidx < norms.Size())
|
||||
{
|
||||
nvec = new FVector3(RealignVector(norms[nidx]));
|
||||
nvec = RealignVector(norms[nidx]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal
|
||||
// Find other sides of triangle
|
||||
auto nextSidx = side + 2;
|
||||
if (nextSidx >= 3) nextSidx -= 3;
|
||||
|
||||
auto lastSidx = side + 1;
|
||||
if (lastSidx >= 3) lastSidx -= 3;
|
||||
|
||||
OBJFaceSide &nextSide = surfaces[i].tris[j].sides[nextSidx];
|
||||
OBJFaceSide &lastSide = surfaces[i].tris[j].sides[lastSidx];
|
||||
|
||||
// Cross-multiply the U-vector and V-vector
|
||||
FVector3 uvec = RealignVector(verts[nextSide.vertref]) - curVvec;
|
||||
FVector3 vvec = RealignVector(verts[lastSide.vertref]) - curVvec;
|
||||
|
||||
nvec = new FVector3(uvec ^ vvec);
|
||||
if (surfaces[i].tris[j].smoothGroup == 0)
|
||||
{
|
||||
nvec = CalculateNormalFlat(i, j);
|
||||
}
|
||||
else
|
||||
{
|
||||
nvec = CalculateNormalSmooth(vidx, surfaces[i].tris[j].smoothGroup);
|
||||
}
|
||||
}
|
||||
mdv->SetNormal(nvec->X, nvec->Y, nvec->Z);
|
||||
delete nvec;
|
||||
mdv->SetNormal(nvec.X, nvec.Y, nvec.Z);
|
||||
}
|
||||
}
|
||||
delete[] surfaces[i].tris;
|
||||
}
|
||||
|
||||
// Destroy vertFaces
|
||||
if (hasMissingNormals && hasSmoothGroups)
|
||||
{
|
||||
for (size_t i = 0; i < verts.Size(); i++)
|
||||
{
|
||||
vertFaces[i].Clear();
|
||||
}
|
||||
delete[] vertFaces;
|
||||
}
|
||||
vbuf->UnlockVertexBuffer();
|
||||
}
|
||||
|
||||
|
@ -432,6 +458,7 @@ void FOBJModel::ConstructSurfaceTris(OBJSurface &surf)
|
|||
surf.tris[triIdx].sideCount = 3;
|
||||
if (faces[i].sideCount == 3)
|
||||
{
|
||||
surf.tris[triIdx].smoothGroup = faces[i].smoothGroup;
|
||||
memcpy(surf.tris[triIdx].sides, faces[i].sides, sizeof(OBJFaceSide) * 3);
|
||||
}
|
||||
else if (faces[i].sideCount == 4) // Triangulate face
|
||||
|
@ -443,6 +470,7 @@ void FOBJModel::ConstructSurfaceTris(OBJSurface &surf)
|
|||
delete[] triangulated;
|
||||
triIdx += 1; // Filling out two faces
|
||||
}
|
||||
DPrintf(DMSG_SPAMMY, "Smooth group: %d\n", surf.tris[triIdx].smoothGroup);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,7 +483,9 @@ void FOBJModel::ConstructSurfaceTris(OBJSurface &surf)
|
|||
void FOBJModel::TriangulateQuad(const OBJFace &quad, OBJFace *tris)
|
||||
{
|
||||
tris[0].sideCount = 3;
|
||||
tris[0].smoothGroup = quad.smoothGroup;
|
||||
tris[1].sideCount = 3;
|
||||
tris[1].smoothGroup = quad.smoothGroup;
|
||||
|
||||
int tsidx[2][3] = {{0, 1, 3}, {1, 2, 3}};
|
||||
|
||||
|
@ -470,6 +500,26 @@ void FOBJModel::TriangulateQuad(const OBJFace &quad, OBJFace *tris)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the vertices of all surfaces' triangles to the array of vertex->triangle references
|
||||
*/
|
||||
void FOBJModel::AddVertFaces() {
|
||||
// Initialize and populate vertFaces - this array stores references to triangles per vertex
|
||||
vertFaces = new TArray<OBJTriRef>[verts.Size()];
|
||||
for (unsigned int i = 0; i < surfaces.Size(); i++)
|
||||
{
|
||||
for (unsigned int j = 0; j < surfaces[i].numTris; j++)
|
||||
{
|
||||
OBJTriRef otr = OBJTriRef(i, j);
|
||||
for (size_t k = 0; k < surfaces[i].tris[j].sideCount; k++)
|
||||
{
|
||||
int vidx = surfaces[i].tris[j].sides[k].vertref;
|
||||
vertFaces[vidx].Push(otr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-align a vector to match MD3 alignment
|
||||
*
|
||||
|
@ -494,6 +544,65 @@ inline FVector2 FOBJModel::FixUV(FVector2 vecToRealign)
|
|||
return vecToRealign;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the surface normal for a triangle
|
||||
*
|
||||
* @param surfIdx The surface index
|
||||
* @param triIdx The triangle Index
|
||||
* @return The surface normal vector
|
||||
*/
|
||||
FVector3 FOBJModel::CalculateNormalFlat(unsigned int surfIdx, unsigned int triIdx)
|
||||
{
|
||||
// https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal
|
||||
int curVert = surfaces[surfIdx].tris[triIdx].sides[0].vertref;
|
||||
int nextVert = surfaces[surfIdx].tris[triIdx].sides[2].vertref;
|
||||
int lastVert = surfaces[surfIdx].tris[triIdx].sides[1].vertref;
|
||||
|
||||
// Cross-multiply the U-vector and V-vector
|
||||
FVector3 curVvec = RealignVector(verts[curVert]);
|
||||
FVector3 uvec = RealignVector(verts[nextVert]) - curVvec;
|
||||
FVector3 vvec = RealignVector(verts[lastVert]) - curVvec;
|
||||
|
||||
return uvec ^ vvec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the surface normal for a triangle
|
||||
*
|
||||
* @param otr A reference to the surface, and a triangle within that surface, as an OBJTriRef
|
||||
* @return The surface normal vector
|
||||
*/
|
||||
FVector3 FOBJModel::CalculateNormalFlat(OBJTriRef otr)
|
||||
{
|
||||
return CalculateNormalFlat(otr.surf, otr.tri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the normal of a vertex in a specific smooth group
|
||||
*
|
||||
* @param vidx The index of the vertex in the array of vertices
|
||||
* @param smoothGroup The smooth group number
|
||||
*/
|
||||
FVector3 FOBJModel::CalculateNormalSmooth(unsigned int vidx, unsigned int smoothGroup)
|
||||
{
|
||||
unsigned int connectedFaces = 0;
|
||||
TArray<OBJTriRef>& vTris = vertFaces[vidx];
|
||||
|
||||
FVector3 vNormal(0,0,0);
|
||||
for (size_t face = 0; face < vTris.Size(); face++)
|
||||
{
|
||||
OBJFace& tri = surfaces[vTris[face].surf].tris[vTris[face].tri];
|
||||
if (tri.smoothGroup == smoothGroup)
|
||||
{
|
||||
FVector3 fNormal = CalculateNormalFlat(vTris[face]);
|
||||
connectedFaces += 1;
|
||||
vNormal += fNormal;
|
||||
}
|
||||
}
|
||||
vNormal /= (float)connectedFaces;
|
||||
return vNormal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the index of the frame with the given name
|
||||
*
|
||||
|
|
|
@ -30,6 +30,8 @@ class FOBJModel : public FModel
|
|||
{
|
||||
private:
|
||||
const char *newSideSep = "$"; // OBJ side separator is /, which is parsed as a line comment by FScanner if two of them are next to each other.
|
||||
bool hasMissingNormals;
|
||||
bool hasSmoothGroups;
|
||||
|
||||
enum class FaceElement
|
||||
{
|
||||
|
@ -38,6 +40,14 @@ private:
|
|||
VNormalIndex
|
||||
};
|
||||
|
||||
struct OBJTriRef
|
||||
{
|
||||
unsigned int surf;
|
||||
unsigned int tri;
|
||||
OBJTriRef(): surf(0), tri(0) {}
|
||||
OBJTriRef(unsigned int surf, unsigned int tri): surf(surf), tri(tri) {}
|
||||
bool operator== (OBJTriRef other) { return surf == other.surf && tri == other.tri; }
|
||||
};
|
||||
struct OBJFaceSide
|
||||
{
|
||||
int vertref;
|
||||
|
@ -47,7 +57,9 @@ private:
|
|||
struct OBJFace
|
||||
{
|
||||
unsigned int sideCount;
|
||||
unsigned int smoothGroup;
|
||||
OBJFaceSide sides[4];
|
||||
OBJFace(): sideCount(0), smoothGroup(0) {}
|
||||
};
|
||||
struct OBJSurface // 1 surface per 'usemtl'
|
||||
{
|
||||
|
@ -66,16 +78,21 @@ private:
|
|||
TArray<OBJFace> faces;
|
||||
TArray<OBJSurface> surfaces;
|
||||
FScanner sc;
|
||||
TArray<OBJTriRef>* vertFaces;
|
||||
|
||||
int ResolveIndex(int origIndex, FaceElement el);
|
||||
template<typename T, size_t L> void ParseVector(TArray<T> &array);
|
||||
bool ParseFaceSide(const FString &side, OBJFace &face, int sidx);
|
||||
void ConstructSurfaceTris(OBJSurface &surf);
|
||||
int ResolveIndex(int origIndex, FaceElement el);
|
||||
void AddVertFaces();
|
||||
void TriangulateQuad(const OBJFace &quad, OBJFace *tris);
|
||||
FVector3 RealignVector(FVector3 vecToRealign);
|
||||
FVector2 FixUV(FVector2 vecToRealign);
|
||||
FVector3 CalculateNormalFlat(unsigned int surfIdx, unsigned int triIdx);
|
||||
FVector3 CalculateNormalFlat(OBJTriRef otr);
|
||||
FVector3 CalculateNormalSmooth(unsigned int vidx, unsigned int smoothGroup);
|
||||
public:
|
||||
FOBJModel() {}
|
||||
FOBJModel(): hasMissingNormals(false), hasSmoothGroups(false), vertFaces(nullptr) {}
|
||||
~FOBJModel();
|
||||
bool Load(const char* fn, int lumpnum, const char* buffer, int length) override;
|
||||
int FindFrame(const char* name) override;
|
||||
|
|
|
@ -2442,7 +2442,9 @@ OPTVAL_FOO_DUMB = "foo_dumb";
|
|||
OPTVAL_ALIASING = "Aliasing";
|
||||
OPTVAL_LINEAR = "Linear";
|
||||
OPTVAL_NEAREST = "Nearest";
|
||||
OPTVAL_PCF = "PCF";
|
||||
OPTVAL_PCF_LOW = "PCF (Low)";
|
||||
OPTVAL_PCF_MEDIUM = "PCF (Medium)";
|
||||
OPTVAL_PCF_HIGH = "PCF (High)";
|
||||
OPTVAL_CUBIC = "Cubic";
|
||||
OPTVAL_BLEP = "Band-limited step";
|
||||
OPTVAL_LINEARSLOW = "Linear (Slower)";
|
||||
|
|
|
@ -2419,7 +2419,9 @@ OPTVAL_DEFAULT = "Défaut";
|
|||
OPTVAL_SOUNDSYSTEM = "Système Sonore";
|
||||
OPTVAL_LINEAR = "Linéaire";
|
||||
OPTVAL_NEAREST = "Nearest";
|
||||
OPTVAL_PCF = "PCF";
|
||||
OPTVAL_PCF_LOW = "PCF (Low)";
|
||||
OPTVAL_PCF_MEDIUM = "PCF (Medium)";
|
||||
OPTVAL_PCF_HIGH = "PCF (High)";
|
||||
OPTVAL_CUBIC = "Cubique";
|
||||
OPTVAL_BLEP = "Step limité sur bande";
|
||||
OPTVAL_LINEARSLOW = "Linéaire (Lent)";
|
||||
|
|
|
@ -2261,7 +2261,9 @@ OptionValue ShadowMapQuality
|
|||
OptionValue ShadowMapFilter
|
||||
{
|
||||
0, "$OPTVAL_NEAREST"
|
||||
1, "$OPTVAL_PCF"
|
||||
1, "$OPTVAL_PCF_LOW"
|
||||
2, "$OPTVAL_PCF_MEDIUM"
|
||||
3, "$OPTVAL_PCF_HIGH"
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -178,47 +178,26 @@ float shadowDirToU(vec2 dir)
|
|||
}
|
||||
}
|
||||
|
||||
float sampleShadowmap(vec2 dir, float v)
|
||||
vec2 shadowUToDir(float u)
|
||||
{
|
||||
float u = shadowDirToU(dir);
|
||||
float dist2 = dot(dir, dir);
|
||||
return step(dist2, texture(ShadowMap, vec2(u, v)).x);
|
||||
u *= 4.0;
|
||||
vec2 raydir;
|
||||
switch (int(u))
|
||||
{
|
||||
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;
|
||||
}
|
||||
return raydir;
|
||||
}
|
||||
|
||||
float sampleShadowmapLinear(vec2 dir, float v)
|
||||
float sampleShadowmap(vec3 planePoint, float v)
|
||||
{
|
||||
float u = shadowDirToU(dir);
|
||||
float dist2 = dot(dir, dir);
|
||||
float bias = 1.0;
|
||||
float negD = dot(vWorldNormal.xyz, planePoint);
|
||||
|
||||
vec2 isize = textureSize(ShadowMap, 0);
|
||||
vec2 size = vec2(isize);
|
||||
|
||||
vec2 fetchPos = vec2(u, v) * size - vec2(0.5, 0.0);
|
||||
if (fetchPos.x < 0.0)
|
||||
fetchPos.x += size.x;
|
||||
|
||||
ivec2 ifetchPos = ivec2(fetchPos);
|
||||
int y = ifetchPos.y;
|
||||
|
||||
float t = fract(fetchPos.x);
|
||||
int x0 = ifetchPos.x;
|
||||
int x1 = ifetchPos.x + 1;
|
||||
if (x1 == isize.x)
|
||||
x1 = 0;
|
||||
|
||||
float depth0 = texelFetch(ShadowMap, ivec2(x0, y), 0).x;
|
||||
float depth1 = texelFetch(ShadowMap, ivec2(x1, y), 0).x;
|
||||
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);
|
||||
vec3 ray = planePoint;
|
||||
|
||||
vec2 isize = textureSize(ShadowMap, 0);
|
||||
float scale = float(isize.x) * 0.25;
|
||||
|
@ -239,51 +218,70 @@ vec2 shadowmapAdjustedRay(vec4 lightpos)
|
|||
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;
|
||||
vec2 dir = ray.xz * t;
|
||||
|
||||
float u = shadowDirToU(dir);
|
||||
float dist2 = dot(dir, dir);
|
||||
return step(dist2, texture(ShadowMap, vec2(u, v)).x);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Check if light is in shadow using Percentage Closer Filtering (PCF)
|
||||
//
|
||||
//===========================================================================
|
||||
float sampleShadowmapPCF(vec3 planePoint, float v)
|
||||
{
|
||||
float bias = 1.0;
|
||||
float negD = dot(vWorldNormal.xyz, planePoint);
|
||||
|
||||
vec3 ray = planePoint;
|
||||
|
||||
if (abs(ray.z) > abs(ray.x))
|
||||
ray.y = ray.y / abs(ray.z);
|
||||
else
|
||||
ray.y = ray.y / abs(ray.x);
|
||||
|
||||
vec2 isize = textureSize(ShadowMap, 0);
|
||||
float scale = float(isize.x);
|
||||
float texelPos = floor(shadowDirToU(ray.xz) * scale);
|
||||
|
||||
float sum = 0.0;
|
||||
float step_count = uShadowmapFilter;
|
||||
|
||||
texelPos -= step_count + 0.5;
|
||||
for (float x = -step_count; x <= step_count; x++)
|
||||
{
|
||||
float u = fract(texelPos / scale);
|
||||
vec2 dir = shadowUToDir(u);
|
||||
|
||||
ray.x = dir.x;
|
||||
ray.z = dir.y;
|
||||
float t = negD / dot(vWorldNormal.xyz, ray) - bias;
|
||||
dir = ray.xz * t;
|
||||
|
||||
float dist2 = dot(dir, dir);
|
||||
sum += step(dist2, texture(ShadowMap, vec2(u, v)).x);
|
||||
texelPos++;
|
||||
}
|
||||
return sum / (uShadowmapFilter * 2.0 + 1.0);
|
||||
}
|
||||
|
||||
float shadowmapAttenuation(vec4 lightpos, float shadowIndex)
|
||||
{
|
||||
if (shadowIndex >= 1024.0)
|
||||
return 1.0; // No shadowmap available for this light
|
||||
|
||||
float v = (shadowIndex + 0.5) / 1024.0;
|
||||
vec3 planePoint = pixelpos.xyz - lightpos.xyz;
|
||||
|
||||
vec2 ray = shadowmapAdjustedRay(lightpos);
|
||||
if (dot(planePoint.xz, planePoint.xz) < 1.0)
|
||||
return 1.0; // Light is too close
|
||||
|
||||
float v = (shadowIndex + 0.5) / 1024.0;
|
||||
|
||||
if (uShadowmapFilter <= 0)
|
||||
{
|
||||
return sampleShadowmap(ray, v);
|
||||
//return sampleShadowmapLinear(ray, v);
|
||||
return sampleShadowmap(planePoint, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
||||
float sum = 0.0;
|
||||
float step_count = ((uShadowmapFilter - 1) / 2.);
|
||||
|
||||
for (float x = -step_count; x <= step_count; x++)
|
||||
{
|
||||
sum += sampleShadowmap(ray + normal * x /*- bias * abs(x)*/, v);
|
||||
}
|
||||
return sum / uShadowmapFilter;
|
||||
return sampleShadowmapPCF(planePoint, v);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -179,26 +179,29 @@ class ThrustFloor : Actor
|
|||
while (it.Next())
|
||||
{
|
||||
let targ = it.thing;
|
||||
double blockdist = radius + it.thing.radius;
|
||||
if (abs(targ.pos.x - it.Position.X) >= blockdist || abs(targ.pos.y - it.Position.Y) >= blockdist)
|
||||
continue;
|
||||
|
||||
// Q: Make this z-aware for everything? It never was before.
|
||||
if (targ.pos.z + targ.height < pos.z || targ.pos.z > pos.z + height)
|
||||
if (targ != null)
|
||||
{
|
||||
if (CurSector.PortalGroup != targ.CurSector.PortalGroup)
|
||||
double blockdist = radius + targ.radius;
|
||||
if (abs(targ.pos.x - it.Position.X) >= blockdist || abs(targ.pos.y - it.Position.Y) >= blockdist)
|
||||
continue;
|
||||
|
||||
// Q: Make this z-aware for everything? It never was before.
|
||||
if (targ.pos.z + targ.height < pos.z || targ.pos.z > pos.z + height)
|
||||
{
|
||||
if (CurSector.PortalGroup != targ.CurSector.PortalGroup)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!targ.bShootable)
|
||||
continue;
|
||||
|
||||
if (targ == self)
|
||||
continue; // don't clip against self
|
||||
|
||||
int newdam = targ.DamageMobj (self, self, 10001, 'Crush');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : 10001, null);
|
||||
args[1] = 1; // Mark thrust thing as bloody
|
||||
}
|
||||
|
||||
if (!targ.bShootable)
|
||||
continue;
|
||||
|
||||
if (targ == self)
|
||||
continue; // don't clip against self
|
||||
|
||||
int newdam = targ.DamageMobj (self, self, 10001, 'Crush');
|
||||
targ.TraceBleed (newdam > 0 ? newdam : 10001, null);
|
||||
args[1] = 1; // Mark thrust thing as bloody
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -540,14 +540,19 @@ class CompatibilityMenu : OptionMenu
|
|||
class GLTextureGLOptions : OptionMenu
|
||||
{
|
||||
private int mWarningIndex;
|
||||
private string mWarningLabel;
|
||||
|
||||
override void Init(Menu parent, OptionMenuDescriptor desc)
|
||||
{
|
||||
super.Init(parent, desc);
|
||||
|
||||
// Find index of warning item placeholder
|
||||
mWarningIndex = -1;
|
||||
mWarningLabel = "!HQRESIZE_WARNING!";
|
||||
|
||||
for (int i=0; i < mDesc.mItems.Size(); ++i)
|
||||
{
|
||||
if (mDesc.mItems[i].mLabel == "!HQRESIZE_WARNING!")
|
||||
if (mDesc.mItems[i].mLabel == mWarningLabel)
|
||||
{
|
||||
mWarningIndex = i;
|
||||
break;
|
||||
|
@ -555,11 +560,22 @@ class GLTextureGLOptions : OptionMenu
|
|||
}
|
||||
}
|
||||
|
||||
override void OnDestroy()
|
||||
{
|
||||
// Restore warning item placeholder
|
||||
if (mWarningIndex >= 0)
|
||||
{
|
||||
mDesc.mItems[mWarningIndex].mLabel = mWarningLabel;
|
||||
}
|
||||
|
||||
Super.OnDestroy();
|
||||
}
|
||||
|
||||
override void Ticker()
|
||||
{
|
||||
Super.Ticker();
|
||||
|
||||
if (mWarningIndex > 0)
|
||||
if (mWarningIndex >= 0)
|
||||
{
|
||||
string message;
|
||||
|
||||
|
|
|
@ -1545,11 +1545,6 @@ pointlight MANA1
|
|||
offset 0 36 0
|
||||
}
|
||||
|
||||
object Mana1
|
||||
{
|
||||
frame MAN1 { light MANA1 }
|
||||
}
|
||||
|
||||
// Green mana
|
||||
pointlight MANA2
|
||||
{
|
||||
|
@ -1559,11 +1554,6 @@ pointlight MANA2
|
|||
offset 0 36 0
|
||||
}
|
||||
|
||||
object Mana2
|
||||
{
|
||||
frame MAN2 { light MANA2 }
|
||||
}
|
||||
|
||||
// Combined mana
|
||||
pointlight MANA3
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue