This commit is contained in:
2025-11-28 23:13:44 +05:30
commit a3a8e79709
7360 changed files with 1156074 additions and 0 deletions

View File

@ -0,0 +1,15 @@
#include <tessellation_entry.cg>
#include <noise.cg>
//--------------------------------------------------------------------------------------
// Functions
//--------------------------------------------------------------------------------------
void computeOffsetAndNormal(in float3 vLocalPos, in float3 vFaceNormal, in float3 vBaryCoords,
inout float3 vOffset, inout float3 vNormal)
{
vOffset = inoiseOffset(vLocalPos);
vNormal = vFaceNormal;
//vNormal = inoiseNormal(vLocalPos, vFaceNormal);
}

View File

@ -0,0 +1,24 @@
#include <tessellation_entry.cg>
//--------------------------------------------------------------------------------------
// Textures
//--------------------------------------------------------------------------------------
DECLARE_TEXTURE_3D(displacementTexture)
//--------------------------------------------------------------------------------------
// Functions
//--------------------------------------------------------------------------------------
void computeOffsetAndNormal(in float3 localPos, in float3 faceNormal, in float3 baryCoords,
inout float3 vOffset, inout float3 vNormal)
{
// There is a slight discrepancy between procedural and textured
// noise, easily fixed by a constant multiplier
static const float multiplier = .35;
float4 texOffset = displacementTexture.SampleLevel(displacementTextureSamplerState, localPos * g_tessUVScale.x, 0);
vOffset = texOffset.xyz * multiplier;
// TODO: use iNoiseNormal
vNormal = faceNormal;
}

View File

@ -0,0 +1,312 @@
#ifndef TESSELLATION_ENTRY_CG
#define TESSELLATION_ENTRY_CG
#include <config.cg>
#include <globals.cg>
uniform const float wavelength;
uniform const float amplitude;
uniform const float tessellation = 5.0f;
uniform const float compressionMin = 0.05f;
uniform const float compressionMax = 0.2f;
uniform const float harmonics = 0.0f;
DECLARE_TEXTURE(profile)
//--------------------------------------------------------------------------------------
// Structures
//--------------------------------------------------------------------------------------
struct VertexOut
{
FragmentParameters params;
float4 screenSpacePosition : POSITION;
};
struct HullConstOut
{
float Edges[3] : SV_TessFactor;
float Inside : SV_InsideTessFactor;
};
struct HullControlOut
{
float3 b300 : SEMANTIC_PN_COEFF0;
float3 b030 : SEMANTIC_PN_COEFF1;
float3 b003 : SEMANTIC_PN_COEFF2;
float3 b210 : SEMANTIC_PN_COEFF3;
float3 b120 : SEMANTIC_PN_COEFF4;
float3 b021 : SEMANTIC_PN_COEFF5;
float3 b012 : SEMANTIC_PN_COEFF6;
float3 b102 : SEMANTIC_PN_COEFF7;
float3 b201 : SEMANTIC_PN_COEFF8;
float3 b111 : SEMANTIC_PN_COEFF9;
float3 normal[3] : SEMANTIC_PN_COEFF10;
float3 tangent[3] : SEMANTIC_PN_COEFF13;
float3 binormal[3] : SEMANTIC_PN_COEFF16;
float4 compression[3] : SEMANTIC_PN_COEFF19;
float4 texcoord[3] : SEMANTIC_PN_COEFF22;
};
struct DomainOut
{
FragmentParameters params;
float4 screenSpacePosition : SV_POSITION;
};
//--------------------------------------------------------------------------------------
// Hull shader
//--------------------------------------------------------------------------------------
HullConstOut ConstantsHS( InputPatch<VertexOut, 3> inputPatch, uint uPID : SV_PrimitiveID )
{
HullConstOut output = (HullConstOut)0;
// float4 vEdgeTessellationFactors = g_tessFactor.xxxy;
// float3 vEdgeFactor;
// bool3 vInterior;
// Assign tessellation levels
output.Edges[0] = tessellation;
output.Edges[1] = tessellation;
output.Edges[2] = tessellation;
output.Inside = tessellation;
return output;
}
[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(1)]
[patchconstantfunc("ConstantsHS")]
[maxtessfactor(15.0)]
HullControlOut hmain( InputPatch<VertexOut, 3> inputPatch, uint uCPID : SV_OutputControlPointID )
{
HullControlOut oPatch;
const float3 v1 = inputPatch[0].params.worldSpacePosition;
const float3 v2 = inputPatch[1].params.worldSpacePosition;
const float3 v3 = inputPatch[2].params.worldSpacePosition;
const float3 n1 = inputPatch[0].params.worldSpaceNormal;
const float3 n2 = inputPatch[1].params.worldSpaceNormal;
const float3 n3 = inputPatch[2].params.worldSpaceNormal;
// Set the control points of the output patch
oPatch.b300 = v1;
oPatch.b030 = v2;
oPatch.b003 = v3;
float w12 = dot(v2-v1, n1);
float w21 = dot(v1-v2, n2);
float w23 = dot(v3-v2, n2);
float w32 = dot(v2-v3, n3);
float w31 = dot(v1-v3, n3);
float w13 = dot(v3-v1, n1);
oPatch.b210 = (2.0f*v1 + v2 - w12*n1)/3.0f;
oPatch.b120 = (2.0f*v2 + v1 - w21*n2)/3.0f;
oPatch.b021 = (2.0f*v2 + v3 - w23*n2)/3.0f;
oPatch.b012 = (2.0f*v3 + v2 - w32*n3)/3.0f;
oPatch.b102 = (2.0f*v3 + v1 - w31*n3)/3.0f;
oPatch.b201 = (2.0f*v1 + v3 - w13*n1)/3.0f;
float3 e = (oPatch.b210 + oPatch.b120 + oPatch.b021 + oPatch.b012 + oPatch.b102 + oPatch.b201) / 6.0f;
float3 v = (v1 + v2 + v3) / 3.0f;
oPatch.b111 = e + (e-v)/2.0f;
oPatch.normal[0] = n1;
oPatch.normal[1] = n2;
oPatch.normal[2] = n3;
oPatch.tangent[0] = inputPatch[0].params.worldSpaceTangent;
oPatch.tangent[1] = inputPatch[1].params.worldSpaceTangent;
oPatch.tangent[2] = inputPatch[2].params.worldSpaceTangent;
oPatch.binormal[0] = inputPatch[0].params.worldSpaceBinormal;
oPatch.binormal[1] = inputPatch[1].params.worldSpaceBinormal;
oPatch.binormal[2] = inputPatch[2].params.worldSpaceBinormal;
oPatch.compression[0] = float4(swizzle(inputPatch[0].params.color));
oPatch.compression[1] = float4(swizzle(inputPatch[1].params.color));
oPatch.compression[2] = float4(swizzle(inputPatch[2].params.color));
oPatch.texcoord[0] = inputPatch[0].params.texcoord0;
oPatch.texcoord[1] = inputPatch[1].params.texcoord0;
oPatch.texcoord[2] = inputPatch[2].params.texcoord0;
return oPatch;
}
//--------------------------------------------------------------------------------------
// Domain Shader
//--------------------------------------------------------------------------------------
float cube(float x) { return x*x*x; }
float sqr(float x) { return x*x; }
float wrinkleProfile(float theta, float r)
{
// standard sinusoid (biased above surface)
//return cos(theta)*0.5f + 0.5f;
// squared sinusoid
//return sqr(cos(theta))*0.5f + 0.5f;
// cubed sinusoid
return cube(cos(theta))*0.5f + 0.5f;
// harmonic frequency
//return lerp(cos(theta), 0.5f*cos(2.0f*theta), r*harmonics)*0.5f + 0.5f;
// texture profile
//const float k2Pi = 6.2831853f;
//return profile.SampleLevel(profileSamplerState, float2(theta/k2Pi, 0.5f), 0.0f).x;
}
float wrinkleProfileDeriv(float theta, float r)
{
// standard sinusoid
//return -sin(theta)*0.5f;
// squared sinusoid
//return -2.0f*cos(theta)*sin(theta)*0.5f;
// cubed sinusoid
return -3.0f*sqr(cos(theta))*sin(theta)*0.5f;
// harmonic frequency
//return 0.5f*lerp(-sin(theta), -sin(2.0f*theta), r*harmonics);
/*
// texture based
const float k2Pi = 6.2831853f;
// approximate texture profile derivative with finite differences
float h1 = profile.SampleLevel(profileSamplerState, float2(theta/k2Pi, 0.5f), 0.0f, int2(-1, 0)).x;
float h2 = profile.SampleLevel(profileSamplerState, float2(theta/k2Pi, 0.5f), 0.0f, int2( 1, 0)).x;
return (h2-h1)*256.0f/(k2Pi*2.0f);
*/
}
float frequencyFunc(float compression, float baseFrequency)
{
const float k2Pi = 6.2831853f;
// decrease wavelength as compression increases
//return k2Pi/baseWavelength;
//return k2Pi/(max(sqr(1.0f-compression), 0.2f)*baseWavelength);
//return k2Pi*max(baseWavelength*compression, 0.1f*baseWavelength);
return k2Pi*lerp(baseFrequency*0.1f, baseFrequency, compression);
}
float amplitudeFunc(float compression)
{
// proportional to compression
return compression;
// parabola with zeros at 0, 1
//return 1.0f - sqr(compression*2.0f-1.0f);
}
float wrinkleFunc(float3 vertex, float3 vertexCompression, float3 x, float baseFrequency, float phaseOffset, float scale, out float3 dhdx)
{
// project test point onto axis of compression
float r = length(vertexCompression);
if (r < 0.001f)
{
dhdx = 0.0f;
return 0.0f;
}
float3 axis = vertexCompression/r;
const float frequency = frequencyFunc(r, baseFrequency);
const float amplitude = amplitudeFunc(r)*scale/frequency;
float theta = frequency*dot(axis, x-vertex) + phaseOffset;
// normal offset
dhdx = amplitude*frequency*axis*wrinkleProfileDeriv(theta, r);
// height offset
return amplitude*wrinkleProfile(theta, r);
}
float interpolate1d(float a, float b, float c, float u, float v, float w)
{
return a*u + b*v + c*w;
}
float3 interpolate3d(float3 a, float3 b, float3 c, float u, float v, float w)
{
return a*u + b*v + c*w;
}
[domain("tri")]
DomainOut dmain( HullConstOut input,
float3 BarycentricCoordinates : SV_DomainLocation,
const OutputPatch<HullControlOut, 1> oPatch )
{
DomainOut output;
// ordering from the original paper
float u = BarycentricCoordinates.y;
float v = BarycentricCoordinates.z;
float w = BarycentricCoordinates.x;
float3 x = oPatch[0].b300*w*w*w +
oPatch[0].b030*u*u*u +
oPatch[0].b003*v*v*v +
oPatch[0].b210*3.0f*w*w*u +
oPatch[0].b120*3.0f*w*u*u +
oPatch[0].b201*3.0f*w*w*v +
oPatch[0].b021*3.0f*u*u*v +
oPatch[0].b102*3.0f*w*v*v +
oPatch[0].b012*3.0f*u*v*v +
oPatch[0].b111*6.0f*w*u*v;
// normal ordering
u = BarycentricCoordinates.x;
v = BarycentricCoordinates.y;
w = BarycentricCoordinates.z;
float3 n1;
float3 n2;
float3 n3;
float lambda = 1.0f/wavelength;
float h1 = wrinkleFunc(oPatch[0].b300, oPatch[0].compression[0].xyz, x, lambda, oPatch[0].compression[0].w, amplitude, n1);
float h2 = wrinkleFunc(oPatch[0].b030, oPatch[0].compression[1].xyz, x, lambda, oPatch[0].compression[1].w, amplitude, n2);
float h3 = wrinkleFunc(oPatch[0].b003, oPatch[0].compression[2].xyz, x, lambda, oPatch[0].compression[2].w, amplitude, n3);
float h = interpolate1d(h1, h2, h3, u, v, w);
float3 n = normalize(interpolate3d(oPatch[0].normal[0], oPatch[0].normal[1], oPatch[0].normal[2], u, v, w));
// artificallly strengthen normal displacement to enhance wrinkles
const float kNormalScale = 2.0f;
output.params.worldSpacePosition = x + h*n;
output.params.worldSpaceNormal = normalize(n - kNormalScale*interpolate3d(n1, n2, n3, u, v, w));
output.params.worldSpaceTangent = 0.0f;//interpolate3d(oPatch[0].tangent[1], oPatch[0].tangent[2], oPatch[0].tangent[0], u, v, w);
output.params.worldSpaceBinormal = 0.0f;//interpolate3d(oPatch[0].binormal[1], oPatch[0].binormal[2], oPatch[0].binormal[0], u, v, w);
output.params.texcoord0 = oPatch[0].texcoord[0]*u + oPatch[0].texcoord[1]*v + oPatch[0].texcoord[2]*w;
output.params.texcoord1 = 0.0;
output.params.texcoord2 = 0.0;
output.params.texcoord3 = 0.0;
//output.params.color.xyz = half3(h, h, h);
//output.params.color.w = 1.0;
output.params.color = 1.0;
// Transform world position with viewprojection matrix
output.screenSpacePosition = mul(g_projMatrix, mul(g_viewMatrix, float4(output.params.worldSpacePosition, 1.0)));
return output;
}
#endif