Rewrite the GLSL ray trace code so it does not use global variables!!
Fix portals not working
This commit is contained in:
parent
445170e33f
commit
c1d0963da4
8 changed files with 151 additions and 171 deletions
|
|
@ -630,7 +630,7 @@ void VkLevelMeshUploader::UploadPortals()
|
|||
|
||||
size_t copysize = range.Size * sizeof(PortalInfo);
|
||||
if (copysize > 0)
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->PortalBuffer.get(), range.Offset * sizeof(PortalInfo), 0, copysize);
|
||||
cmdbuffer->copyBuffer(transferBuffer.get(), Mesh->PortalBuffer.get(), datapos, range.Offset * sizeof(PortalInfo), copysize);
|
||||
datapos += copysize;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,7 +198,9 @@ bool DoomLevelMesh::TraceSky(const FVector3& start, FVector3 direction, float di
|
|||
|
||||
int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLight* list, int listMaxSize)
|
||||
{
|
||||
FLightNode* node = GetSurfaceLightNode(static_cast<const DoomLevelMeshSurface*>(surface));
|
||||
std::pair<FLightNode*, int> nodePortalGroup = GetSurfaceLightNode(static_cast<const DoomLevelMeshSurface*>(surface));
|
||||
FLightNode* node = nodePortalGroup.first;
|
||||
int portalgroup = nodePortalGroup.second;
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
|
|
@ -208,7 +210,7 @@ int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLi
|
|||
FDynamicLight* light = node->lightsource;
|
||||
if (light && light->Trace())
|
||||
{
|
||||
DVector3 pos = light->Pos; //light->PosRelative(portalgroup);
|
||||
DVector3 pos = light->PosRelative(portalgroup);
|
||||
|
||||
LevelMeshLight& meshlight = list[listpos++];
|
||||
meshlight.Origin = { (float)pos.X, (float)pos.Y, (float)pos.Z };
|
||||
|
|
@ -251,12 +253,14 @@ int DoomLevelMesh::AddSurfaceLights(const LevelMeshSurface* surface, LevelMeshLi
|
|||
return listpos;
|
||||
}
|
||||
|
||||
FLightNode* DoomLevelMesh::GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf)
|
||||
std::pair<FLightNode*, int> DoomLevelMesh::GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf)
|
||||
{
|
||||
FLightNode* node = nullptr;
|
||||
int portalgroup = 0;
|
||||
if (doomsurf->Type == ST_FLOOR || doomsurf->Type == ST_CEILING)
|
||||
{
|
||||
node = doomsurf->Subsector->section->lighthead;
|
||||
portalgroup = doomsurf->Subsector->sector->PortalGroup;
|
||||
}
|
||||
else if (doomsurf->Type == ST_MIDDLESIDE || doomsurf->Type == ST_UPPERSIDE || doomsurf->Type == ST_LOWERSIDE)
|
||||
{
|
||||
|
|
@ -265,18 +269,21 @@ FLightNode* DoomLevelMesh::GetSurfaceLightNode(const DoomLevelMeshSurface* dooms
|
|||
{
|
||||
subsector_t* subsector = level.PointInRenderSubsector((doomsurf->Side->V1()->fPos() + doomsurf->Side->V2()->fPos()) * 0.5);
|
||||
node = subsector->section->lighthead;
|
||||
portalgroup = subsector->sector->PortalGroup;
|
||||
}
|
||||
else if (!doomsurf->ControlSector)
|
||||
{
|
||||
node = doomsurf->Side->lighthead;
|
||||
portalgroup = doomsurf->Side->sector->PortalGroup;
|
||||
}
|
||||
else // 3d floor needs light from the sidedef on the other side
|
||||
{
|
||||
int otherside = doomsurf->Side->linedef->sidedef[0] == doomsurf->Side ? 1 : 0;
|
||||
node = doomsurf->Side->linedef->sidedef[otherside]->lighthead;
|
||||
portalgroup = doomsurf->Side->linedef->sidedef[otherside]->sector->PortalGroup;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
return { node, portalgroup };
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreateSurfaces(FLevelLocals& doomMap)
|
||||
|
|
@ -1021,9 +1028,10 @@ void DoomLevelMesh::CreatePortals(FLevelLocals& doomMap)
|
|||
auto d = sector->GetPortalDisplacement(plane);
|
||||
if (!d.isZero())
|
||||
{
|
||||
// Note: Y and Z is swapped in the shader due to how the hwrenderer was implemented
|
||||
VSMatrix transformation;
|
||||
transformation.loadIdentity();
|
||||
transformation.translate((float)d.X, (float)d.Y, 0.0f);
|
||||
transformation.translate((float)d.X, 0.0f, (float)d.Y);
|
||||
|
||||
int targetSectorGroup = 0;
|
||||
auto portalDestination = sector->GetPortal(plane)->mDestination;
|
||||
|
|
@ -1089,8 +1097,9 @@ void DoomLevelMesh::CreatePortals(FLevelLocals& doomMap)
|
|||
z = tz - sz;
|
||||
}
|
||||
|
||||
transformation.rotate((float)sourceLine->getPortalAngleDiff().Degrees(), 0.0f, 0.0f, 1.0f);
|
||||
transformation.translate((float)(targetXYZ.X - sourceXYZ.X), (float)(targetXYZ.Y - sourceXYZ.Y), (float)z);
|
||||
// Note: Y and Z is swapped in the shader due to how the hwrenderer was implemented
|
||||
transformation.rotate((float)sourceLine->getPortalAngleDiff().Degrees(), 0.0f, 1.0f, 0.0f);
|
||||
transformation.translate((float)(targetXYZ.X - sourceXYZ.X), (float)z, (float)(targetXYZ.Y - sourceXYZ.Y));
|
||||
|
||||
int targetSectorGroup = 0;
|
||||
if (auto sector = targetLine->frontsector ? targetLine->frontsector : targetLine->backsector)
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ private:
|
|||
int GetSampleDimension(const DoomLevelMeshSurface& surf);
|
||||
|
||||
void CreatePortals(FLevelLocals& doomMap);
|
||||
FLightNode* GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf);
|
||||
std::pair<FLightNode*, int> GetSurfaceLightNode(const DoomLevelMeshSurface* doomsurf);
|
||||
|
||||
TArray<SideSurfaceRange> Sides;
|
||||
TArray<FlatSurfaceRange> Flats;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,17 @@
|
|||
|
||||
struct TraceResult
|
||||
{
|
||||
float t;
|
||||
vec3 primitiveWeights;
|
||||
int primitiveIndex;
|
||||
};
|
||||
|
||||
#if defined(USE_RAYQUERY)
|
||||
|
||||
int TraceFirstHitTriangleNoPortal(vec3 origin, float tmin, vec3 dir, float tmax, out float t, out vec3 primitiveWeights)
|
||||
TraceResult TraceFirstHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
TraceResult result;
|
||||
|
||||
rayQueryEXT rayQuery;
|
||||
rayQueryInitializeEXT(rayQuery, acc, gl_RayFlagsCullBackFacingTrianglesEXT, 0xFF, origin, tmin, dir, tmax);
|
||||
|
||||
|
|
@ -16,18 +25,20 @@ int TraceFirstHitTriangleNoPortal(vec3 origin, float tmin, vec3 dir, float tmax,
|
|||
|
||||
if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionTriangleEXT)
|
||||
{
|
||||
t = rayQueryGetIntersectionTEXT(rayQuery, true);
|
||||
result.t = rayQueryGetIntersectionTEXT(rayQuery, true);
|
||||
|
||||
primitiveWeights.xy = rayQueryGetIntersectionBarycentricsEXT(rayQuery, true);
|
||||
primitiveWeights.z = 1.0 - primitiveWeights.x - primitiveWeights.y;
|
||||
result.primitiveWeights.xy = rayQueryGetIntersectionBarycentricsEXT(rayQuery, true);
|
||||
result.primitiveWeights.z = 1.0 - result.primitiveWeights.x - result.primitiveWeights.y;
|
||||
|
||||
return rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true);
|
||||
result.primitiveIndex = rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = tmax;
|
||||
return -1;
|
||||
result.t = tmax;
|
||||
result.primitiveIndex = -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -234,8 +245,10 @@ TraceHit find_first_hit(RayBBox ray)
|
|||
return hit;
|
||||
}
|
||||
|
||||
int TraceFirstHitTriangleNoPortal(vec3 origin, float tmin, vec3 dir, float tmax, out float tparam, out vec3 primitiveWeights)
|
||||
TraceResult TraceFirstHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
TraceResult result;
|
||||
|
||||
// Perform segmented tracing to keep the ray AABB box smaller
|
||||
vec3 ray_start = origin;
|
||||
vec3 ray_end = origin + dir * tmax;
|
||||
|
|
@ -251,16 +264,17 @@ int TraceFirstHitTriangleNoPortal(vec3 origin, float tmin, vec3 dir, float tmax,
|
|||
TraceHit hit = find_first_hit(ray);
|
||||
if (hit.fraction < 1.0)
|
||||
{
|
||||
tparam = hit.fraction = segstart * (1.0 - hit.fraction) + segend * hit.fraction;
|
||||
primitiveWeights.x = hit.b;
|
||||
primitiveWeights.y = hit.c;
|
||||
primitiveWeights.z = 1.0 - hit.b - hit.c;
|
||||
return hit.triangle;
|
||||
result.t = mix(segstart, segend, hit.fraction);
|
||||
result.primitiveWeights.x = hit.b;
|
||||
result.primitiveWeights.y = hit.c;
|
||||
result.primitiveWeights.z = 1.0 - hit.b - hit.c;
|
||||
result.primitiveIndex = hit.triangle;
|
||||
}
|
||||
}
|
||||
|
||||
tparam = tracedist;
|
||||
return -1;
|
||||
result.t = tracedist;
|
||||
result.primitiveIndex = -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,14 +20,19 @@ float TraceAmbientOcclusion(vec3 origin, vec3 normal)
|
|||
vec3 H = normalize(vec3(Xi.x * 2.0f - 1.0f, Xi.y * 2.0f - 1.0f, 1.5 - length(Xi)));
|
||||
vec3 L = H.x * tangent + H.y * bitangent + H.z * N;
|
||||
|
||||
float hitDistance;
|
||||
int primitiveID = TraceFirstHitTriangleT(origin, minDistance, L, aoDistance, hitDistance);
|
||||
if (primitiveID != -1)
|
||||
TraceResult result = TraceFirstHit(origin, minDistance, L, aoDistance);
|
||||
|
||||
// Ignore surfaces with textures, skies or portals
|
||||
if (result.primitiveIndex != -1)
|
||||
{
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
if (surface.Sky == 0.0)
|
||||
SurfaceInfo surface = GetSurface(result.primitiveIndex);
|
||||
if (surface.Sky == 0.0 && surface.TextureIndex == 0 && surface.PortalIndex == 0)
|
||||
{
|
||||
ambience += clamp(hitDistance / aoDistance, 0.0, 1.0);
|
||||
ambience += clamp(result.t / aoDistance, 0.0, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ambience += 1.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,126 +1,38 @@
|
|||
|
||||
vec4 rayColor;
|
||||
|
||||
vec4 alphaBlend(vec4 a, vec4 b);
|
||||
vec4 BeerLambertSimple(vec4 medium, vec4 ray_color);
|
||||
vec4 blend(vec4 a, vec4 b);
|
||||
|
||||
int TraceFirstHitTriangleT(vec3 origin, float tmin, vec3 dir, float tmax, out float t)
|
||||
SurfaceInfo GetSurface(int primitiveIndex)
|
||||
{
|
||||
int primitiveID = -1;
|
||||
vec3 primitiveWeights;
|
||||
for (int i = 0; i < 4; i++)
|
||||
return surfaces[surfaceIndices[primitiveIndex]];
|
||||
}
|
||||
|
||||
vec2 GetSurfaceUV(int primitiveIndex, vec3 primitiveWeights)
|
||||
{
|
||||
int index = primitiveIndex * 3;
|
||||
return
|
||||
vertices[elements[index + 1]].uv * primitiveWeights.x +
|
||||
vertices[elements[index + 2]].uv * primitiveWeights.y +
|
||||
vertices[elements[index + 0]].uv * primitiveWeights.z;
|
||||
}
|
||||
|
||||
vec4 BlendTexture(SurfaceInfo surface, vec2 uv, vec4 rayColor)
|
||||
{
|
||||
if (surface.TextureIndex == 0)
|
||||
{
|
||||
primitiveID = TraceFirstHitTriangleNoPortal(origin, tmin, dir, tmax, t, primitiveWeights);
|
||||
|
||||
if(primitiveID < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
|
||||
if(surface.PortalIndex == 0)
|
||||
{
|
||||
int index = primitiveID * 3;
|
||||
vec2 uv = vertices[elements[index + 1]].uv * primitiveWeights.x + vertices[elements[index + 2]].uv * primitiveWeights.y + vertices[elements[index + 0]].uv * primitiveWeights.z;
|
||||
|
||||
if (surface.TextureIndex == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
vec4 color = texture(textures[surface.TextureIndex], uv);
|
||||
color.w *= surface.Alpha;
|
||||
|
||||
if (color.w > 0.999 || all(lessThan(rayColor.rgb, vec3(0.001))))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
rayColor = blend(color, rayColor);
|
||||
}
|
||||
|
||||
// Portal was hit: Apply transformation onto the ray
|
||||
mat4 transformationMatrix = portals[surface.PortalIndex].Transformation;
|
||||
|
||||
origin = (transformationMatrix * vec4(origin + dir * t, 1.0)).xyz;
|
||||
dir = (transformationMatrix * vec4(dir, 0.0)).xyz;
|
||||
tmax -= t;
|
||||
return rayColor;
|
||||
}
|
||||
return primitiveID;
|
||||
}
|
||||
|
||||
int TraceFirstHitTriangle(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
float t;
|
||||
return TraceFirstHitTriangleT(origin, tmin, dir, tmax, t);
|
||||
}
|
||||
|
||||
bool TraceAnyHit(vec3 origin, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
return TraceFirstHitTriangle(origin, tmin, dir, tmax) >= 0;
|
||||
}
|
||||
|
||||
bool TracePoint(vec3 origin, vec3 target, float tmin, vec3 dir, float tmax)
|
||||
{
|
||||
int primitiveID;
|
||||
float t;
|
||||
vec3 primitiveWeights;
|
||||
for (int i = 0; i < 4; i++)
|
||||
else
|
||||
{
|
||||
t = tmax;
|
||||
primitiveID = TraceFirstHitTriangleNoPortal(origin, tmin, dir, tmax, t, primitiveWeights);
|
||||
|
||||
origin += dir * t;
|
||||
tmax -= t;
|
||||
|
||||
if(primitiveID < 0)
|
||||
{
|
||||
// We didn't hit anything
|
||||
break;
|
||||
}
|
||||
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
|
||||
if (surface.PortalIndex == 0)
|
||||
{
|
||||
int index = primitiveID * 3;
|
||||
vec2 uv = vertices[elements[index + 1]].uv * primitiveWeights.x + vertices[elements[index + 2]].uv * primitiveWeights.y + vertices[elements[index + 0]].uv * primitiveWeights.z;
|
||||
|
||||
if (surface.TextureIndex == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
vec4 color = texture(textures[surface.TextureIndex], uv);
|
||||
color.w *= surface.Alpha;
|
||||
|
||||
if (color.w > 0.999 || all(lessThan(rayColor.rgb, vec3(0.001))))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
rayColor = blend(color, rayColor);
|
||||
}
|
||||
|
||||
if(dot(surface.Normal, dir) >= 0.0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
mat4 transformationMatrix = portals[surface.PortalIndex].Transformation;
|
||||
origin = (transformationMatrix * vec4(origin, 1.0)).xyz;
|
||||
dir = (transformationMatrix * vec4(dir, 0.0)).xyz;
|
||||
vec4 color = texture(textures[surface.TextureIndex], uv);
|
||||
return BeerLambertSimple(vec4(1.0 - color.rgb, color.a * surface.Alpha), rayColor);
|
||||
}
|
||||
|
||||
return distance(origin, target) <= 1.0;
|
||||
}
|
||||
|
||||
vec4 alphaBlend(vec4 a, vec4 b)
|
||||
void TransformRay(uint portalIndex, inout vec3 origin, inout vec3 dir)
|
||||
{
|
||||
float na = a.w + b.w * (1.0 - a.w);
|
||||
return vec4((a.xyz * a.w + b.xyz * b.w * (1.0 - a.w)) / na, max(0.001, na));
|
||||
mat4 transformationMatrix = portals[portalIndex].Transformation;
|
||||
origin = (transformationMatrix * vec4(origin, 1.0)).xyz;
|
||||
dir = (transformationMatrix * vec4(dir, 0.0)).xyz;
|
||||
}
|
||||
|
||||
vec4 BeerLambertSimple(vec4 medium, vec4 ray_color) // based on Beer-Lambert law
|
||||
|
|
@ -129,9 +41,3 @@ vec4 BeerLambertSimple(vec4 medium, vec4 ray_color) // based on Beer-Lambert law
|
|||
ray_color.rgb *= exp(-medium.rgb * vec3(z));
|
||||
return ray_color;
|
||||
}
|
||||
|
||||
vec4 blend(vec4 a, vec4 b)
|
||||
{
|
||||
return BeerLambertSimple(vec4(1.0 - a.rgb, a.w), b);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
vec4 TracePointLightRay(vec3 origin, vec3 lightpos, float tmin, vec4 rayColor);
|
||||
vec2 getVogelDiskSample(int sampleIndex, int sampleCount, float phi);
|
||||
|
||||
vec3 TraceLight(vec3 origin, vec3 normal, LightInfo light, int surfaceIndex)
|
||||
|
|
@ -27,6 +28,8 @@ vec3 TraceLight(vec3 origin, vec3 normal, LightInfo light, int surfaceIndex)
|
|||
float attenuation = distAttenuation * angleAttenuation * spotAttenuation;
|
||||
if (attenuation > 0.0)
|
||||
{
|
||||
vec4 rayColor = vec4(light.Color.rgb * (attenuation * light.Intensity), 1.0);
|
||||
|
||||
#if defined(USE_SOFTSHADOWS)
|
||||
|
||||
vec3 v = (abs(dir.x) > abs(dir.y)) ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
|
||||
|
|
@ -40,19 +43,11 @@ vec3 TraceLight(vec3 origin, vec3 normal, LightInfo light, int surfaceIndex)
|
|||
vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * lightsize;
|
||||
vec3 pos = light.Origin + xdir * gridoffset.x + ydir * gridoffset.y;
|
||||
|
||||
rayColor = vec4(light.Color.rgb, 1.0);
|
||||
if (TracePoint(origin, pos, minDistance, normalize(pos - origin), distance(origin, pos)))
|
||||
{
|
||||
incoming.rgb += (rayColor.rgb * rayColor.w) * (attenuation * light.Intensity) / float(step_count);
|
||||
}
|
||||
incoming.rgb += TracePointLightRay(origin, pos, minDistance, rayColor).rgb / float(step_count);
|
||||
}
|
||||
|
||||
#else
|
||||
rayColor = vec4(light.Color.rgb, 1.0);
|
||||
if(TracePoint(origin, light.Origin, minDistance, dir, dist))
|
||||
{
|
||||
incoming.rgb += (rayColor.rgb * rayColor.w) * (attenuation * light.Intensity);
|
||||
}
|
||||
incoming.rgb += TracePointLightRay(origin, light.Origin, minDistance, rayColor).rgb;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -60,6 +55,38 @@ vec3 TraceLight(vec3 origin, vec3 normal, LightInfo light, int surfaceIndex)
|
|||
return incoming;
|
||||
}
|
||||
|
||||
vec4 TracePointLightRay(vec3 origin, vec3 lightpos, float tmin, vec4 rayColor)
|
||||
{
|
||||
vec3 dir = normalize(lightpos - origin);
|
||||
float tmax = distance(origin, lightpos);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
TraceResult result = TraceFirstHit(origin, tmin, dir, tmax);
|
||||
|
||||
// We hit nothing. Point light is visible.
|
||||
if (result.primitiveIndex == -1)
|
||||
return rayColor;
|
||||
|
||||
SurfaceInfo surface = GetSurface(result.primitiveIndex);
|
||||
|
||||
// Blend with surface texture
|
||||
rayColor = BlendTexture(surface, GetSurfaceUV(result.primitiveIndex, result.primitiveWeights), rayColor);
|
||||
|
||||
// Stop if it isn't a portal, or there is no light left
|
||||
if (surface.PortalIndex == 0 || rayColor.r + rayColor.g + rayColor.b <= 0.0)
|
||||
return vec4(0.0);
|
||||
|
||||
// Move to surface hit point
|
||||
origin += dir * result.t;
|
||||
tmax -= result.t;
|
||||
|
||||
// Move through the portal
|
||||
TransformRay(surface.PortalIndex, origin, dir);
|
||||
}
|
||||
return vec4(0.0);
|
||||
}
|
||||
|
||||
vec2 getVogelDiskSample(int sampleIndex, int sampleCount, float phi)
|
||||
{
|
||||
const float goldenAngle = radians(180.0) * (3.0 - sqrt(5.0));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
vec2 getVogelDiskSample(int sampleIndex, int sampleCount, float phi);
|
||||
vec4 TraceSunRay(vec3 origin, float tmin, vec3 dir, float tmax, vec4 rayColor);
|
||||
|
||||
vec3 TraceSunLight(vec3 origin, vec3 normal, int surfaceIndex)
|
||||
{
|
||||
|
|
@ -15,6 +16,8 @@ vec3 TraceSunLight(vec3 origin, vec3 normal, int surfaceIndex)
|
|||
vec3 incoming = vec3(0.0);
|
||||
const float dist = 65536.0;
|
||||
|
||||
vec4 rayColor = vec4(SunColor.rgb * SunIntensity, 1.0);
|
||||
|
||||
#if defined(USE_SOFTSHADOWS)
|
||||
|
||||
vec3 target = origin + SunDir * dist;
|
||||
|
|
@ -29,29 +32,45 @@ vec3 TraceSunLight(vec3 origin, vec3 normal, int surfaceIndex)
|
|||
{
|
||||
vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * lightsize;
|
||||
vec3 pos = target + xdir * gridoffset.x + ydir * gridoffset.y;
|
||||
|
||||
rayColor = vec4(SunColor.rgb * SunIntensity, 1.0);
|
||||
|
||||
int primitiveID = TraceFirstHitTriangle(origin, minDistance, normalize(pos - origin), dist);
|
||||
if (primitiveID != -1)
|
||||
{
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
incoming.rgb += rayColor.rgb * rayColor.w * surface.Sky / float(step_count);
|
||||
}
|
||||
incoming.rgb += TraceSunRay(origin, minDistance, normalize(pos - origin), dist, rayColor).rgb / float(step_count);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
rayColor = vec4(SunColor.rgb * SunIntensity, 1.0);
|
||||
|
||||
int primitiveID = TraceFirstHitTriangle(origin, minDistance, SunDir, dist);
|
||||
if (primitiveID != -1)
|
||||
{
|
||||
SurfaceInfo surface = surfaces[surfaceIndices[primitiveID]];
|
||||
incoming.rgb = rayColor.rgb * rayColor.w * surface.Sky;
|
||||
}
|
||||
incoming.rgb = TraceSunRay(origin, minDistance, SunDir, dist, rayColor).rgb;
|
||||
|
||||
#endif
|
||||
|
||||
return incoming * angleAttenuation;
|
||||
}
|
||||
|
||||
vec4 TraceSunRay(vec3 origin, float tmin, vec3 dir, float tmax, vec4 rayColor)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
TraceResult result = TraceFirstHit(origin, tmin, dir, tmax);
|
||||
|
||||
// We hit nothing. We have to hit a sky surface to hit the sky.
|
||||
if (result.primitiveIndex == -1)
|
||||
return vec4(0.0);
|
||||
|
||||
SurfaceInfo surface = GetSurface(result.primitiveIndex);
|
||||
|
||||
// Blend with surface texture
|
||||
rayColor = BlendTexture(surface, GetSurfaceUV(result.primitiveIndex, result.primitiveWeights), rayColor);
|
||||
|
||||
// Stop if it isn't a portal, or there is no light left
|
||||
if (surface.PortalIndex == 0 || rayColor.r + rayColor.g + rayColor.b <= 0.0)
|
||||
return rayColor * surface.Sky;
|
||||
|
||||
// Move to surface hit point
|
||||
origin += dir * result.t;
|
||||
tmax -= result.t;
|
||||
if (tmax <= tmin)
|
||||
return vec4(0.0);
|
||||
|
||||
// Move through the portal
|
||||
TransformRay(surface.PortalIndex, origin, dir);
|
||||
}
|
||||
return vec4(0.0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue