wip(standalone): GPU step 6 -- near field on GPU, exact; cold start still slower than CPU
Near LOD0/1 (detail band, relief, root refinement, normals) now evaluated and meshed on the GPU. 960 near tiles: zero sign/topology differences vs CPU and WARP, vertex max 0.0049 mm (was 15 cm); far survival audit passes; CPU hashes 44/44 unchanged. Far connector-panel outlier (64.56 cm, LOD8) remains a tessellation difference, and remote captures show missing far geometry on GPU. Cold readiness (viewer clock, my interleaved runs): CPU 2.51/2.49/2.40 s, GPU 5.05/2.68/2.80 s. The ~2.1 s Present stall hit only the first GPU launch. Viewer spends ~1.13 s before shape compile starts (startup checks), which is the gap between the 0.95 s benchmark and ~2.4 s on-screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
0e730cdbba
commit
b0a14262b1
50 files changed
+1681
-236
No files matched your search
@@ -68,6 +68,7 @@ static const VF_FieldI32 VF_FIELD_PRIMITIVE_HAS_FLOOR = 8;
|
||||
static const VF_FieldI32 VF_FIELD_PRIMITIVE_CURVED_FLOOR = 16;
|
||||
static const VF_FieldI32 VF_FIELD_PRIMITIVE_CARVE = 32;
|
||||
static const VF_FieldI32 VF_FIELD_PRIMITIVE_CRITICAL = 64;
|
||||
static const VF_FieldI32 VF_FIELD_PRIMITIVE_PASSAGE = 128;
|
||||
|
||||
VF_FIELD_INLINE VF_FieldReal VF_FieldEvaluateFloorProfile(VF_FieldReal a, VF_FieldReal b,
|
||||
VF_FieldReal tangentA, VF_FieldReal tangentB, VF_FieldReal length,
|
||||
@@ -249,6 +250,193 @@ VF_FIELD_INLINE float VF_FieldSurfaceRelief(float x, float y, float z, VF_FieldU
|
||||
return 1.20f * macro + (0.80f + 0.25f * macro) * (0.40f * mid + 0.60f * fine);
|
||||
}
|
||||
|
||||
// Scalar version of VoxelNoise::Perlin3D and its owner-world roughness variant.
|
||||
// The integer hash and operation order are shared so the standalone field and HLSL
|
||||
// evaluate the same authored detail from the same world parameters.
|
||||
VF_FIELD_INLINE VF_FieldU32 VF_FieldVoxelHashMix(VF_FieldU32 x)
|
||||
{
|
||||
x ^= x >> 16; x *= 0x45d9f3bu;
|
||||
x ^= x >> 16; x *= 0x45d9f3bu;
|
||||
x ^= x >> 16;
|
||||
return x;
|
||||
}
|
||||
|
||||
VF_FIELD_INLINE float VF_FieldVoxelSeedOffset(VF_FieldU32 seed,float siteKey)
|
||||
{
|
||||
const VF_FieldU32 site=VF_FIELD_CAST_U32(siteKey*100.0f+0.5f);
|
||||
return VF_FIELD_CAST_F32(VF_FieldVoxelHashMix(seed^(site*2654435761u))&0x3FFFu);
|
||||
}
|
||||
|
||||
VF_FIELD_INLINE VF_FieldU32 VF_FieldPerlinHash(VF_FieldI32 x,VF_FieldI32 y,VF_FieldI32 z)
|
||||
{
|
||||
VF_FieldU32 h=VF_FIELD_CAST_U32(x)*0x9E3779B1u
|
||||
^VF_FIELD_CAST_U32(y)*0x85EBCA77u
|
||||
^VF_FIELD_CAST_U32(z)*0xC2B2AE3Du;
|
||||
h^=h>>15;h*=0x2C1B3C6Du;
|
||||
h^=h>>12;h*=0x297A2D39u;
|
||||
h^=h>>15;
|
||||
return h;
|
||||
}
|
||||
|
||||
VF_FIELD_INLINE float VF_FieldPerlinFade(float t)
|
||||
{
|
||||
const float inner=t*(t*6.0f-15.0f)+10.0f;
|
||||
const float t3=t*t*t;
|
||||
return t3*inner;
|
||||
}
|
||||
|
||||
VF_FIELD_INLINE float VF_FieldPerlinGrad(VF_FieldU32 hash,float x,float y,float z)
|
||||
{
|
||||
const VF_FieldU32 h=hash&15u;
|
||||
const float u=(h&8u)==0u?x:y;
|
||||
float v;
|
||||
if((h&12u)==0u)v=y;
|
||||
else if((h&13u)==12u)v=x;
|
||||
else v=z;
|
||||
const float ru=(h&1u)==0u?u:-u;
|
||||
const float rv=(h&2u)==0u?v:-v;
|
||||
return ru+rv;
|
||||
}
|
||||
|
||||
VF_FIELD_INLINE float VF_FieldPerlinLerp(float a,float b,float t)
|
||||
{ return a+t*(b-a); }
|
||||
|
||||
VF_FIELD_INLINE float VF_FieldPerlin3D(float x,float y,float z)
|
||||
{
|
||||
const float xf=VF_FIELD_FLOOR(x),yf=VF_FIELD_FLOOR(y),zf=VF_FIELD_FLOOR(z);
|
||||
const VF_FieldI32 X=VF_FIELD_CAST_I32(xf),Y=VF_FIELD_CAST_I32(yf),Z=VF_FIELD_CAST_I32(zf);
|
||||
const float fx=x-xf,fy=y-yf,fz=z-zf;
|
||||
const float su=VF_FieldPerlinFade(fx),sv=VF_FieldPerlinFade(fy),sw=VF_FieldPerlinFade(fz);
|
||||
const VF_FieldU32 h000=VF_FieldPerlinHash(X,Y,Z),h100=VF_FieldPerlinHash(X+1,Y,Z);
|
||||
const VF_FieldU32 h010=VF_FieldPerlinHash(X,Y+1,Z),h110=VF_FieldPerlinHash(X+1,Y+1,Z);
|
||||
const VF_FieldU32 h001=VF_FieldPerlinHash(X,Y,Z+1),h101=VF_FieldPerlinHash(X+1,Y,Z+1);
|
||||
const VF_FieldU32 h011=VF_FieldPerlinHash(X,Y+1,Z+1),h111=VF_FieldPerlinHash(X+1,Y+1,Z+1);
|
||||
const float fx1=fx-1.0f,fy1=fy-1.0f,fz1=fz-1.0f;
|
||||
const float n000=VF_FieldPerlinGrad(h000,fx,fy,fz);
|
||||
const float n100=VF_FieldPerlinGrad(h100,fx1,fy,fz);
|
||||
const float n010=VF_FieldPerlinGrad(h010,fx,fy1,fz);
|
||||
const float n110=VF_FieldPerlinGrad(h110,fx1,fy1,fz);
|
||||
const float n001=VF_FieldPerlinGrad(h001,fx,fy,fz1);
|
||||
const float n101=VF_FieldPerlinGrad(h101,fx1,fy,fz1);
|
||||
const float n011=VF_FieldPerlinGrad(h011,fx,fy1,fz1);
|
||||
const float n111=VF_FieldPerlinGrad(h111,fx1,fy1,fz1);
|
||||
const float x00=VF_FieldPerlinLerp(n000,n100,su);
|
||||
const float x10=VF_FieldPerlinLerp(n010,n110,su);
|
||||
const float x01=VF_FieldPerlinLerp(n001,n101,su);
|
||||
const float x11=VF_FieldPerlinLerp(n011,n111,su);
|
||||
const float y0=VF_FieldPerlinLerp(x00,x10,sv);
|
||||
const float y1=VF_FieldPerlinLerp(x01,x11,sv);
|
||||
return VF_FieldPerlinLerp(y0,y1,sw);
|
||||
}
|
||||
|
||||
VF_FIELD_INLINE float VF_FieldOwnerFractal(float x,float y,float z,VF_FieldI32 octaves,
|
||||
VF_FieldI32 mode)
|
||||
{
|
||||
float total=0.0f,maxValue=0.0f,frequency=1.0f,amplitude=1.0f,weight=1.0f;
|
||||
for(VF_FieldI32 i=0;i<octaves;++i)
|
||||
{
|
||||
const float noise=VF_FieldPerlin3D(x*frequency,y*frequency,z*frequency);
|
||||
if(mode==0)total+=noise*amplitude;
|
||||
else
|
||||
{
|
||||
float ridge=noise*1.25f;
|
||||
ridge=1.0f-VF_FIELD_ABS(ridge);
|
||||
ridge=ridge*ridge;
|
||||
ridge*=weight;
|
||||
weight=VF_FIELD_CLAMP(ridge*2.0f,0.0f,1.0f);
|
||||
total+=ridge*amplitude;
|
||||
}
|
||||
maxValue+=amplitude;
|
||||
amplitude*=0.5f;
|
||||
frequency*=2.0f;
|
||||
}
|
||||
const float result=total/maxValue;
|
||||
return mode==0?result:result*2.0f-1.0f;
|
||||
}
|
||||
|
||||
VF_FIELD_INLINE float VF_FieldOwnerCellular(float x,float y,float z)
|
||||
{
|
||||
const VF_FieldI32 cellX=VF_FIELD_CAST_I32(VF_FIELD_FLOOR(x));
|
||||
const VF_FieldI32 cellY=VF_FIELD_CAST_I32(VF_FIELD_FLOOR(y));
|
||||
const VF_FieldI32 cellZ=VF_FIELD_CAST_I32(VF_FIELD_FLOOR(z));
|
||||
const float fracX=x-VF_FIELD_CAST_F32(cellX),fracY=y-VF_FIELD_CAST_F32(cellY),
|
||||
fracZ=z-VF_FIELD_CAST_F32(cellZ);
|
||||
float first=3.402823466e+38f,second=3.402823466e+38f;
|
||||
for(VF_FieldI32 dz=-1;dz<=1;++dz)
|
||||
for(VF_FieldI32 dy=-1;dy<=1;++dy)
|
||||
for(VF_FieldI32 dx=-1;dx<=1;++dx)
|
||||
{
|
||||
const VF_FieldI32 nx=cellX+dx,ny=cellY+dy,nz=cellZ+dz;
|
||||
const VF_FieldU32 h=VF_FieldVoxelHashMix(
|
||||
VF_FIELD_CAST_U32(nx+0x7FFFFFFF)
|
||||
^VF_FieldVoxelHashMix(VF_FIELD_CAST_U32(ny+0x7FFFFFFF)*2654435761u)
|
||||
^VF_FieldVoxelHashMix(VF_FIELD_CAST_U32(nz+0x7FFFFFFF)*374761393u));
|
||||
const float fpx=VF_FIELD_CAST_F32(dx)
|
||||
+VF_FIELD_CAST_F32(h&0xFFFFFFu)*(1.0f/16777216.0f)-fracX;
|
||||
const VF_FieldU32 hy=VF_FieldVoxelHashMix(h^0x12345678u);
|
||||
const VF_FieldU32 hz=VF_FieldVoxelHashMix(h^0x9ABCDEF0u);
|
||||
const float fpy=VF_FIELD_CAST_F32(dy)
|
||||
+VF_FIELD_CAST_F32(hy&0xFFFFFFu)*(1.0f/16777216.0f)-fracY;
|
||||
const float fpz=VF_FIELD_CAST_F32(dz)
|
||||
+VF_FIELD_CAST_F32(hz&0xFFFFFFu)*(1.0f/16777216.0f)-fracZ;
|
||||
const float distanceSquared=fpx*fpx+fpy*fpy+fpz*fpz;
|
||||
if(distanceSquared<first){second=first;first=distanceSquared;}
|
||||
else if(distanceSquared<second)second=distanceSquared;
|
||||
}
|
||||
return (VF_FIELD_SQRT(second)-VF_FIELD_SQRT(first))*2.0f-1.0f;
|
||||
}
|
||||
|
||||
VF_FIELD_INLINE float VF_FieldOwnerRoughnessCore(float x,float y,float z,
|
||||
VF_FieldU32 seed,float surfaceRoughness,float roughnessFrequency,float verticalScale,
|
||||
float domainWarpStrength,float domainWarpFrequency,VF_FieldU32 noiseType)
|
||||
{
|
||||
if(!(roughnessFrequency>0.0f))return 0.0f;
|
||||
const float effectiveZ=verticalScale>0.0f&&verticalScale!=1.0f?z/verticalScale:z;
|
||||
const float mainX=x*roughnessFrequency+VF_FieldVoxelSeedOffset(seed,11.3f);
|
||||
const float mainY=y*roughnessFrequency+VF_FieldVoxelSeedOffset(seed,13.7f);
|
||||
const float mainZ=effectiveZ*roughnessFrequency+VF_FieldVoxelSeedOffset(seed,17.1f);
|
||||
float fineX=x*roughnessFrequency*3.0f+VF_FieldVoxelSeedOffset(seed,19.1f)+2000.0f;
|
||||
float fineY=y*roughnessFrequency*3.0f+VF_FieldVoxelSeedOffset(seed,23.7f)+2500.0f;
|
||||
float fineZ=effectiveZ*roughnessFrequency*3.0f+VF_FieldVoxelSeedOffset(seed,29.3f)+3000.0f;
|
||||
float mx=mainX,my=mainY,mz=mainZ;
|
||||
if(domainWarpStrength>0.0f)
|
||||
{
|
||||
const float wf=domainWarpFrequency,ws=domainWarpStrength;
|
||||
float wx=VF_FieldPerlin3D(x*wf+VF_FieldVoxelSeedOffset(seed,5.2f),
|
||||
y*wf+VF_FieldVoxelSeedOffset(seed,1.3f),
|
||||
effectiveZ*wf+VF_FieldVoxelSeedOffset(seed,9.7f));
|
||||
float wy=VF_FieldPerlin3D(x*wf+100.0f+VF_FieldVoxelSeedOffset(seed,7.7f),
|
||||
y*wf+200.0f+VF_FieldVoxelSeedOffset(seed,3.1f),effectiveZ*wf+300.0f);
|
||||
float wz=VF_FieldPerlin3D(x*wf+400.0f,y*wf+500.0f+VF_FieldVoxelSeedOffset(seed,11.9f),
|
||||
effectiveZ*wf+600.0f+VF_FieldVoxelSeedOffset(seed,13.3f));
|
||||
wx*=1.25f*ws;wy*=1.25f*ws;wz*=1.25f*ws;
|
||||
mx+=wx;my+=wy;mz+=wz;
|
||||
fineX+=wx;fineY+=wy;fineZ+=wz;
|
||||
}
|
||||
float rough=0.0f,fine=0.0f;
|
||||
if(noiseType==1u)
|
||||
{
|
||||
rough=VF_FieldOwnerFractal(mx,my,mz,3,1);
|
||||
fine=VF_FieldOwnerFractal(fineX,fineY,fineZ,2,1);
|
||||
}
|
||||
else if(noiseType==2u)
|
||||
{
|
||||
rough=(VF_FieldOwnerFractal(mx,my,mz,3,0)+VF_FieldOwnerFractal(mx,my,mz,3,1))*0.5f;
|
||||
fine=(VF_FieldOwnerFractal(fineX,fineY,fineZ,2,0)+VF_FieldOwnerFractal(fineX,fineY,fineZ,2,1))*0.5f;
|
||||
}
|
||||
else if(noiseType==3u)
|
||||
{
|
||||
rough=VF_FieldOwnerCellular(mx,my,mz);
|
||||
fine=VF_FieldOwnerCellular(fineX,fineY,fineZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
rough=VF_FieldOwnerFractal(mx,my,mz,3,0);
|
||||
fine=VF_FieldOwnerFractal(fineX,fineY,fineZ,2,0);
|
||||
}
|
||||
return (rough+fine*0.4f)*1.25f*surfaceRoughness;
|
||||
}
|
||||
|
||||
VF_FIELD_INLINE float VF_FieldSmoothUnit(float value)
|
||||
{
|
||||
#if defined(VF_FIELD_HLSL)
|
||||
|
||||
Reference in new issue
Block a user