forked from aya/aya
426 lines
13 KiB
Scala
426 lines
13 KiB
Scala
$input a_position, a_normal, a_texcoord0, a_texcoord1, a_color0, a_color1, a_texcoord2, a_texcoord3
|
|
$output v_pos, v_worldPos, v_texcoord0, v_texcoord1, v_color0, v_normal, v_tangent, v_lightpos_fog, v_view_depth, v_poslightspace, v_edgedist, v_reflection
|
|
|
|
#include "common.sh"
|
|
|
|
#define LQMAT_FADE_FACTOR (1.0/300.0)
|
|
#define BEVEL_WIDTH 0.06
|
|
#define PI 3.14159265359
|
|
|
|
#define BEVEL_FADE_DIST 120.0
|
|
#define BEVEL_FADE_DIST_START 0.0
|
|
|
|
#define SPEC_EXPON 81.0
|
|
#define KS 0.75
|
|
|
|
#define FADE_DIST 500.0
|
|
#define FADE_DIST_START 0.0
|
|
|
|
uniform vec4 u_worldMatrixArray[MAX_BONE_COUNT * 3];
|
|
uniform vec4 u_debugColor;
|
|
|
|
SAMPLER2D(s_studsMap, 0);
|
|
SAMPLER2D(s_lightMap, 1);
|
|
SAMPLER2D(s_lightMapLookup, 2);
|
|
SAMPLER2D(s_shadowMap, 3);
|
|
SAMPLERCUBE(s_environmentMap, 4);
|
|
SAMPLER2D(s_diffuseMap, 5);
|
|
SAMPLER2D(s_normalMap, 6);
|
|
SAMPLER2D(s_specularMap, 7);
|
|
|
|
#ifndef GLSLES
|
|
SAMPLER2D(s_normalDetailMap, 8);
|
|
#endif
|
|
|
|
uniform vec4 u_lqmatFarTilingFactor;
|
|
|
|
void Shade(vec3 albedo, vec3 nn, vec3 vn, float ks, float specExpon, vec4 light, out vec3 diffuse, out vec3 specular)
|
|
{
|
|
vec3 ln = normalize(-u_lamp0Dir);
|
|
vec3 hn = normalize(ln + vn);
|
|
float ndl = dot(nn, ln);
|
|
float ndh = dot(nn, hn);
|
|
|
|
vec2 lit0 = vec2(max(0.0, ndl), pow(max(0.0, ndh), specExpon) * step(0.0, ndl));
|
|
vec3 lampColor = u_lamp0Color;
|
|
diffuse = (light.a * (lampColor * lit0.x) + u_ambientColor + light.xyz);
|
|
diffuse *= albedo;
|
|
specular = (lampColor * lit0.y) * ks * light.a;
|
|
}
|
|
|
|
vec3 CalcBevel(vec4 edgeDistances, vec3 normal, float viewDepth)
|
|
{
|
|
vec4 bevelMultiplier = clamp((BEVEL_WIDTH - edgeDistances) / BEVEL_WIDTH, 0.0, 1.0);
|
|
float fade = clamp(1.0 - (viewDepth - BEVEL_FADE_DIST_START) / BEVEL_FADE_DIST, 0.0, 1.0);
|
|
bevelMultiplier *= fade;
|
|
|
|
normal += bevelMultiplier.x * vec3(0.5, 0.0, 0.0);
|
|
normal += bevelMultiplier.y * vec3(-0.5, 0.0, 0.0);
|
|
normal += bevelMultiplier.z * vec3(0.0, 0.5, 0.0);
|
|
normal += bevelMultiplier.w * vec3(0.0, -0.5, 0.0);
|
|
|
|
return normalize(normal);
|
|
}
|
|
|
|
vec3 DisplaceCoord(vec3 pos)
|
|
{
|
|
float cfactor = 0.980066578;
|
|
float sfactor = 0.198669331;
|
|
float cfactor2 = 0.955336489;
|
|
float sfactor2 = 0.295520207;
|
|
float cfactor3 = 0.921060994;
|
|
float sfactor3 = 0.389418342;
|
|
vec3 p = pos.xyz;
|
|
vec3 shiftPos = p;
|
|
|
|
shiftPos.x += p.x * cfactor + p.z * sfactor;
|
|
shiftPos.z += p.x * -sfactor + p.z * cfactor;
|
|
|
|
shiftPos.x += p.x * cfactor2 - p.y * sfactor2;
|
|
shiftPos.y += p.x * sfactor2 + p.y * cfactor2;
|
|
|
|
shiftPos.y += p.y * cfactor3 - p.z * sfactor3;
|
|
shiftPos.z += p.y * sfactor3 + p.z * cfactor3;
|
|
|
|
return shiftPos;
|
|
}
|
|
|
|
#ifdef CLASSIC
|
|
|
|
void DefaultVS()
|
|
{
|
|
// Transform position and normal to world space
|
|
#ifdef PIN_SKINNED
|
|
int boneIndex = int(a_color1.r);
|
|
|
|
vec4 worldRow0 = u_worldMatrixArray[boneIndex * 3];
|
|
vec4 worldRow1 = u_worldMatrixArray[boneIndex * 3 + 1];
|
|
vec4 worldRow2 = u_worldMatrixArray[boneIndex * 3 + 2];
|
|
|
|
vec3 posWorld = vec3(dot(worldRow0, vec4(a_position, 1.0)),
|
|
dot(worldRow1, vec4(a_position, 1.0)),
|
|
dot(worldRow2, vec4(a_position, 1.0)));
|
|
vec3 normalWorld = vec3(dot(worldRow0.xyz, a_normal),
|
|
dot(worldRow1.xyz, a_normal),
|
|
dot(worldRow2.xyz, a_normal));
|
|
v_tangent = vec3(dot(worldRow0.xyz, a_texcoord2),
|
|
dot(worldRow1.xyz, a_texcoord2),
|
|
dot(worldRow2.xyz, a_texcoord2));
|
|
#else
|
|
vec3 posWorld = a_position;
|
|
vec3 normalWorld = a_normal;
|
|
v_tangent = a_texcoord2;
|
|
#endif
|
|
v_pos = a_position;
|
|
v_worldPos = posWorld;
|
|
|
|
vec4 color = a_color0;
|
|
|
|
gl_Position = mul(u_viewProjection, vec4(posWorld, 1.0));
|
|
v_normal = normalWorld;
|
|
v_texcoord0 = a_texcoord0;
|
|
v_texcoord1 = a_texcoord1;
|
|
|
|
v_color0 = color;
|
|
v_lightpos_fog = vec4(lgridPrepareSample(lgridOffset(posWorld, normalWorld)),
|
|
(u_fogParams.z - gl_Position.w) * u_fogParams.w);
|
|
|
|
v_view_depth = vec4(u_cameraPosition - posWorld, gl_Position.w);
|
|
|
|
#ifdef CLASSIC_GOURAUD
|
|
vec4 light = lgridSample(s_lightMap, s_lightMapLookup, v_lightpos_fog.xyz);
|
|
vec3 diffuse, specular;
|
|
Shade(vec3(1.0), normalize(v_normal), normalize(v_view_depth.xyz), 0.71, 81.0, light, diffuse, specular);
|
|
// Store in unused varyings
|
|
#endif
|
|
|
|
#if defined(PIN_HQ) || defined(PIN_REFLECTION)
|
|
v_reflection = a_color1.a / 255.0;
|
|
v_edgedist = a_texcoord3;
|
|
#endif
|
|
|
|
v_poslightspace = shadowPrepareSample(posWorld);
|
|
}
|
|
|
|
void DefaultPS()
|
|
{
|
|
float normalStrength = 0.4;
|
|
float fade = clamp(normalStrength - (v_view_depth.w - FADE_DIST_START) / FADE_DIST, 0.0, 1.0);
|
|
vec3 nn = normalize(v_normal);
|
|
vec4 edgeDistances = v_edgedist;
|
|
|
|
vec4 albedo = v_color0;
|
|
vec2 uv;
|
|
|
|
#ifndef PIN_MESH
|
|
uv = v_texcoord0;
|
|
|
|
mat3 normalMatrix = mat3(
|
|
v_tangent.xyz,
|
|
cross(nn, v_tangent.xyz),
|
|
nn
|
|
);
|
|
|
|
vec3 tn = vec3(0.0, 0.0, 0.5);
|
|
tn = mix(vec3(0.0, 0.0, 0.5), tn, fade);
|
|
tn = CalcBevel(edgeDistances, tn, v_view_depth.w);
|
|
nn = mul(tn, normalMatrix);
|
|
|
|
vec4 colorTex = texture2D(s_diffuseMap, uv);
|
|
albedo *= colorTex;
|
|
#else
|
|
uv = v_texcoord0;
|
|
vec4 colorTex = texture2D(s_diffuseMap, uv);
|
|
albedo *= colorTex;
|
|
#endif
|
|
|
|
vec3 vn = normalize(v_view_depth.xyz);
|
|
vec4 light = lgridSample(s_lightMap, s_lightMapLookup, v_lightpos_fog.xyz);
|
|
|
|
vec3 diffusePhong, specularPhong;
|
|
vec3 diffuse, specular;
|
|
|
|
#ifdef CLASSIC_GOURAUD
|
|
// Use pre-computed lighting from vertex shader
|
|
diffuse = albedo.rgb; // Should use stored diffuse from VS
|
|
specular = vec3(0.0); // Should use stored specular from VS
|
|
#else
|
|
Shade(albedo.rgb, nn, vn, KS, SPEC_EXPON, light, diffusePhong, specularPhong);
|
|
diffuse = diffusePhong;
|
|
specular = specularPhong;
|
|
#endif
|
|
|
|
vec3 result = diffuse + specular;
|
|
|
|
#ifdef PIN_REFLECTION
|
|
vec3 reflection = textureCube(s_environmentMap, reflect(-vn, nn)).rgb;
|
|
result = mix(result, reflection, v_reflection);
|
|
#endif
|
|
|
|
float fogAlpha = clamp((u_fogParams.z - length(v_view_depth.xyz)) * u_fogParams.w, 0.0, 1.0);
|
|
result = mix(u_fogColor, result, fogAlpha);
|
|
|
|
gl_FragColor = vec4(result, albedo.a);
|
|
|
|
#ifdef PIN_GBUFFER
|
|
// Output to second render target
|
|
// gl_FragData[1] = gbufferPack(v_view_depth.w, diffuse.rgb, specular.rgb, fogAlpha);
|
|
#endif
|
|
}
|
|
|
|
#else // !CLASSIC - Modern rendering path
|
|
|
|
void DefaultVS()
|
|
{
|
|
// Transform position and normal to world space
|
|
#ifdef PIN_SKINNED
|
|
int boneIndex = int(a_color1.r);
|
|
|
|
vec4 worldRow0 = u_worldMatrixArray[boneIndex * 3 + 0];
|
|
vec4 worldRow1 = u_worldMatrixArray[boneIndex * 3 + 1];
|
|
vec4 worldRow2 = u_worldMatrixArray[boneIndex * 3 + 2];
|
|
|
|
vec3 posWorld = vec3(dot(worldRow0, vec4(a_position, 1.0)),
|
|
dot(worldRow1, vec4(a_position, 1.0)),
|
|
dot(worldRow2, vec4(a_position, 1.0)));
|
|
vec3 normalWorld = vec3(dot(worldRow0.xyz, a_normal),
|
|
dot(worldRow1.xyz, a_normal),
|
|
dot(worldRow2.xyz, a_normal));
|
|
#else
|
|
vec3 posWorld = a_position;
|
|
vec3 normalWorld = a_normal;
|
|
#endif
|
|
|
|
// Decode diffuse/specular parameters
|
|
#ifdef PIN_DEBUG
|
|
vec4 color = u_debugColor;
|
|
#else
|
|
vec4 color = a_color0;
|
|
#endif
|
|
|
|
float specularIntensity = a_color1.g / 255.0;
|
|
float specularPower = float(int(a_color1.b));
|
|
|
|
float ndotl = dot(normalWorld, -u_lamp0Dir);
|
|
|
|
#ifdef PIN_HQ
|
|
// We'll calculate specular in pixel shader
|
|
vec2 lt = vec2(clamp(ndotl, 0.0, 1.0), step(0.0, ndotl));
|
|
#else
|
|
// Using lit here improves performance on software vertex shader implementations
|
|
vec2 lt = vec2(max(0.0, ndotl),
|
|
pow(max(0.0, dot(normalize(-u_lamp0Dir + normalize(u_cameraPosition - posWorld)), normalWorld)), specularPower) * step(0.0, ndotl));
|
|
#endif
|
|
|
|
gl_Position = mul(u_viewProjection, vec4(posWorld, 1.0));
|
|
|
|
v_texcoord0 = a_texcoord0;
|
|
v_texcoord1 = a_texcoord1;
|
|
|
|
v_color0 = color;
|
|
v_lightpos_fog = vec4(lgridPrepareSample(lgridOffset(posWorld, normalWorld)),
|
|
(u_fogParams.z - gl_Position.w) * u_fogParams.w);
|
|
|
|
v_view_depth = vec4(u_cameraPosition - posWorld, gl_Position.w);
|
|
|
|
#if defined(PIN_HQ) || defined(PIN_REFLECTION)
|
|
vec4 edgeDistances = a_texcoord3 * u_fadeDistance_GlowFactor.z + 0.5 * v_view_depth.w * u_fadeDistance_GlowFactor.y;
|
|
|
|
v_edgedist = edgeDistances;
|
|
v_normal = normalWorld;
|
|
// Store specular power in normal.w if needed
|
|
v_reflection = a_color1.a / 255.0;
|
|
#endif
|
|
|
|
#ifdef PIN_SURFACE
|
|
#ifdef PIN_SKINNED
|
|
vec3 tangent = vec3(dot(worldRow0.xyz, a_texcoord2),
|
|
dot(worldRow1.xyz, a_texcoord2),
|
|
dot(worldRow2.xyz, a_texcoord2));
|
|
#else
|
|
vec3 tangent = a_texcoord2;
|
|
#endif
|
|
|
|
v_tangent = tangent;
|
|
#else
|
|
vec3 diffuse = lt.x * u_lamp0Color + max(-ndotl, 0.0) * u_lamp1Color;
|
|
// Store diffuse and specular in color channels (pack into v_color0.w and other varyings)
|
|
#endif
|
|
|
|
v_poslightspace = shadowPrepareSample(posWorld);
|
|
}
|
|
|
|
vec4 sampleFar1(sampler2D s, vec2 uv, float fade, float cutoff)
|
|
{
|
|
#ifdef GLSLES
|
|
return texture2D(s, uv);
|
|
#else
|
|
if (cutoff == 0.0)
|
|
return texture2D(s, uv);
|
|
else
|
|
{
|
|
float cscale = 1.0 / (1.0 - cutoff);
|
|
return mix(texture2D(s, uv * u_lqmatFarTilingFactor.xy),
|
|
texture2D(s, uv),
|
|
saturate0(fade * cscale - cutoff * cscale));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if defined(PIN_WANG) || defined(PIN_WANG_FALLBACK)
|
|
vec4 sampleWangSimple(sampler2D s, vec2 uv)
|
|
{
|
|
vec2 wangUv;
|
|
vec4 wangUVDerivatives;
|
|
getWang(s_normalDetailMap, uv, 1.0, wangUv, wangUVDerivatives);
|
|
return sampleWang(s, wangUv, wangUVDerivatives);
|
|
}
|
|
#endif
|
|
|
|
void DefaultPS()
|
|
{
|
|
// Compute albedo term
|
|
#ifdef PIN_SURFACE
|
|
// Surface shader path - would need surface shader implementation
|
|
vec4 albedo = v_color0;
|
|
vec3 normal = normalize(v_normal);
|
|
#elif defined(PIN_LOWQMAT)
|
|
|
|
#ifndef CFG_FAR_DIFFUSE_CUTOFF
|
|
#define CFG_FAR_DIFFUSE_CUTOFF 0.6
|
|
#endif
|
|
|
|
#if defined(PIN_WANG) || defined(PIN_WANG_FALLBACK)
|
|
vec4 albedo = sampleWangSimple(s_diffuseMap, v_texcoord0);
|
|
#else
|
|
float fade = saturate0(1.0 - v_view_depth.w * LQMAT_FADE_FACTOR);
|
|
vec4 albedo = sampleFar1(s_diffuseMap, v_texcoord0, fade, CFG_FAR_DIFFUSE_CUTOFF);
|
|
#endif
|
|
|
|
albedo.rgb = mix(vec3(1.0), v_color0.rgb, albedo.a) * albedo.rgb;
|
|
albedo.a = v_color0.a;
|
|
|
|
// Diffuse and specular from vertex shader (stored in varyings)
|
|
vec3 diffuseIntensity = vec3(1.0); // Should unpack from varyings
|
|
float specularIntensity = 0.0; // Should unpack from varyings
|
|
float reflectance = 0.0;
|
|
|
|
#else
|
|
#ifdef PIN_PLASTIC
|
|
vec4 studs = texture2D(s_studsMap, v_texcoord1);
|
|
vec4 albedo = vec4(v_color0.rgb * (studs.r * 2.0), v_color0.a);
|
|
#else
|
|
vec4 albedo = texture2D(s_diffuseMap, v_texcoord0) * v_color0;
|
|
#endif
|
|
|
|
#ifdef PIN_HQ
|
|
vec3 normal = normalize(v_normal);
|
|
float specularPower = 81.0; // Should come from varying
|
|
#elif defined(PIN_REFLECTION)
|
|
vec3 normal = v_normal;
|
|
#endif
|
|
|
|
vec3 diffuseIntensity = vec3(1.0); // Should unpack from varyings
|
|
float specularIntensity = 0.0; // Should unpack from varyings
|
|
|
|
#ifdef PIN_REFLECTION
|
|
float reflectance = v_reflection;
|
|
#endif
|
|
|
|
#endif
|
|
|
|
vec4 light = lgridSample(s_lightMap, s_lightMapLookup, v_lightpos_fog.xyz);
|
|
float shadow = shadowSample(s_shadowMap, v_poslightspace, light.a);
|
|
|
|
// Compute reflection term
|
|
#if defined(PIN_SURFACE) || defined(PIN_REFLECTION)
|
|
vec3 reflection = textureCube(s_environmentMap, reflect(-v_view_depth.xyz, normal)).rgb;
|
|
albedo.rgb = mix(albedo.rgb, reflection.rgb, reflectance);
|
|
#endif
|
|
|
|
// Compute diffuse term
|
|
vec3 diffuse = (u_ambientColor + diffuseIntensity * shadow + light.rgb) * albedo.rgb;
|
|
|
|
// Compute specular term
|
|
#ifdef PIN_HQ
|
|
vec3 normal = normalize(v_normal);
|
|
float specularPower = 81.0;
|
|
vec3 specular = u_lamp0Color * (specularIntensity * shadow *
|
|
pow(clamp(dot(normal, normalize(-u_lamp0Dir + normalize(v_view_depth.xyz))), 0.0, 1.0), specularPower));
|
|
#else
|
|
vec3 specular = u_lamp0Color * (specularIntensity * shadow);
|
|
#endif
|
|
|
|
// Combine
|
|
vec3 resultColor = diffuse.rgb + specular.rgb;
|
|
float resultAlpha = albedo.a;
|
|
|
|
#ifdef PIN_HQ
|
|
float ViewDepthMul = v_view_depth.w * u_fadeDistance_GlowFactor.y;
|
|
float outlineFade = saturate1(ViewDepthMul * u_outlineBrightness_ShadowInfo.x + u_outlineBrightness_ShadowInfo.y);
|
|
vec2 minIntermediate = min(v_edgedist.xy, v_edgedist.zw);
|
|
float minEdgesPlus = min(minIntermediate.x, minIntermediate.y) / ViewDepthMul;
|
|
resultColor *= saturate1(outlineFade * (1.5 - minEdgesPlus) + minEdgesPlus);
|
|
#endif
|
|
|
|
float fogAlpha = clamp(v_lightpos_fog.w, 0.0, 1.0);
|
|
|
|
#ifdef PIN_NEON
|
|
resultColor = v_color0.rgb * u_fadeDistance_GlowFactor.w;
|
|
resultAlpha = 1.0 - fogAlpha * v_color0.a;
|
|
diffuse.rgb = vec3(0.0);
|
|
specular.rgb = vec3(0.0);
|
|
#endif
|
|
|
|
resultColor = mix(u_fogColor, resultColor, fogAlpha);
|
|
|
|
gl_FragColor = vec4(resultColor, resultAlpha);
|
|
|
|
#ifdef PIN_GBUFFER
|
|
// Output to second render target
|
|
// gl_FragData[1] = gbufferPack(v_view_depth.w, diffuse.rgb, specular.rgb, fogAlpha);
|
|
#endif
|
|
}
|
|
|
|
#endif // CLASSIC
|