mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
parent
1c99ebcbcc
commit
8953d7ff73
10 changed files with 327 additions and 308 deletions
|
@ -133,7 +133,7 @@ protected:
|
|||
TransformedVertex *transformed = nullptr;
|
||||
TransformedVertex *transformedExpanded = nullptr;
|
||||
|
||||
// Defer all vertex decoding to a "Flush" (except when skinning)
|
||||
// Defer all vertex decoding to a "Flush" (except when software skinning)
|
||||
struct DeferredDrawCall {
|
||||
void *verts;
|
||||
void *inds;
|
||||
|
|
|
@ -41,7 +41,7 @@ static const u8 nrmsize[4] = { 0, 3, 6, 12 }, nrmalign[4] = { 0, 1, 2, 4 };
|
|||
static const u8 possize[4] = { 3, 3, 6, 12 }, posalign[4] = { 1, 1, 2, 4 };
|
||||
static const u8 wtsize[4] = { 0, 1, 2, 4 }, wtalign[4] = { 0, 1, 2, 4 };
|
||||
|
||||
// This array is only used when non-jitted - when jitted, the matrix
|
||||
// When software skinning. This array is only used when non-jitted - when jitted, the matrix
|
||||
// is kept in registers.
|
||||
alignas(16) static float skinMatrix[12];
|
||||
|
||||
|
@ -49,6 +49,13 @@ inline int align(int n, int align) {
|
|||
return (n + (align - 1)) & ~(align - 1);
|
||||
}
|
||||
|
||||
int TranslateNumBones(int bones) {
|
||||
if (!bones) return 0;
|
||||
if (bones < 4) return 4;
|
||||
// if (bones < 8) return 8; I get drawing problems in FF:CC with this!
|
||||
return bones;
|
||||
}
|
||||
|
||||
int DecFmtSize(u8 fmt) {
|
||||
switch (fmt) {
|
||||
case DEC_NONE: return 0;
|
||||
|
|
|
@ -432,6 +432,9 @@ struct JitLookup {
|
|||
JitStepFunction jitFunc;
|
||||
};
|
||||
|
||||
// Collapse to less skinning shaders to reduce shader switching, which is expensive.
|
||||
int TranslateNumBones(int bones);
|
||||
|
||||
typedef void(*JittedVertexDecoder)(const u8 *src, u8 *dst, int count);
|
||||
|
||||
struct VertexDecoderOptions {
|
||||
|
|
|
@ -343,7 +343,7 @@ void DrawEngineD3D11::DoFlush() {
|
|||
|
||||
// Cannot cache vertex data with morph enabled.
|
||||
bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK);
|
||||
// Also avoid caching when skinning.
|
||||
// Also avoid caching when software skinning.
|
||||
if (lastVType_ & GE_VTYPE_WEIGHT_MASK)
|
||||
useCache = false;
|
||||
|
||||
|
|
|
@ -324,7 +324,7 @@ void DrawEngineDX9::DoFlush() {
|
|||
|
||||
// Cannot cache vertex data with morph enabled.
|
||||
bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK);
|
||||
// Also avoid caching when skinning.
|
||||
// Also avoid caching when software skinning.
|
||||
if (lastVType_ & GE_VTYPE_WEIGHT_MASK)
|
||||
useCache = false;
|
||||
|
||||
|
|
|
@ -357,113 +357,116 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// Step 1: World Transform
|
||||
// Hardware tessellation
|
||||
if (doSpline || doBezier) {
|
||||
WRITE(p, " uint num_patches_u = %s;\n", doBezier ? "(u_spline_count_u - 1) / 3u" : "u_spline_count_u - 3");
|
||||
WRITE(p, " float2 tess_pos = In.position.xy;\n");
|
||||
WRITE(p, " int u = In.instanceId %% num_patches_u;\n");
|
||||
WRITE(p, " int v = In.instanceId / num_patches_u;\n");
|
||||
WRITE(p, " int2 patch_pos = int2(u, v);\n");
|
||||
WRITE(p, " float3 _pos[16];\n");
|
||||
WRITE(p, " float2 _tex[16];\n");
|
||||
WRITE(p, " float4 _col[16];\n");
|
||||
WRITE(p, " int idx;\n");
|
||||
WRITE(p, " int2 index;\n");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
WRITE(p, " idx = (%i + v%s) * u_spline_count_u + (%i + u%s);\n", i, doBezier ? " * 3" : "", j, doBezier ? " * 3" : "");
|
||||
WRITE(p, " index = int2(idx, 0);\n");
|
||||
WRITE(p, " _pos[%i] = u_tess_pos_tex.Load(index).xyz;\n", i * 4 + j);
|
||||
if (doTexture && hasTexcoord && hasTexcoordTess)
|
||||
WRITE(p, " _tex[%i] = u_tess_tex_tex.Load(index).xy;\n", i * 4 + j);
|
||||
if (hasColor && hasColorTess)
|
||||
WRITE(p, " _col[%i] = u_tess_col_tex.Load(index).rgba;\n", i * 4 + j);
|
||||
// Step 1: World Transform / Skinning
|
||||
if (true) {
|
||||
// Hardware tessellation
|
||||
if (doSpline || doBezier) {
|
||||
WRITE(p, " uint num_patches_u = %s;\n", doBezier ? "(u_spline_count_u - 1) / 3u" : "u_spline_count_u - 3");
|
||||
WRITE(p, " float2 tess_pos = In.position.xy;\n");
|
||||
WRITE(p, " int u = In.instanceId %% num_patches_u;\n");
|
||||
WRITE(p, " int v = In.instanceId / num_patches_u;\n");
|
||||
WRITE(p, " int2 patch_pos = int2(u, v);\n");
|
||||
WRITE(p, " float3 _pos[16];\n");
|
||||
WRITE(p, " float2 _tex[16];\n");
|
||||
WRITE(p, " float4 _col[16];\n");
|
||||
WRITE(p, " int idx;\n");
|
||||
WRITE(p, " int2 index;\n");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
WRITE(p, " idx = (%i + v%s) * u_spline_count_u + (%i + u%s);\n", i, doBezier ? " * 3" : "", j, doBezier ? " * 3" : "");
|
||||
WRITE(p, " index = int2(idx, 0);\n");
|
||||
WRITE(p, " _pos[%i] = u_tess_pos_tex.Load(index).xyz;\n", i * 4 + j);
|
||||
if (doTexture && hasTexcoord && hasTexcoordTess)
|
||||
WRITE(p, " _tex[%i] = u_tess_tex_tex.Load(index).xy;\n", i * 4 + j);
|
||||
if (hasColor && hasColorTess)
|
||||
WRITE(p, " _col[%i] = u_tess_col_tex.Load(index).rgba;\n", i * 4 + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
WRITE(p, " float2 weights[4];\n");
|
||||
if (doBezier) {
|
||||
// Bernstein 3D
|
||||
WRITE(p, " weights[0] = (1.0 - tess_pos) * (1.0 - tess_pos) * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[1] = 3.0 * tess_pos * (1.0 - tess_pos) * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[2] = 3.0 * tess_pos * tess_pos * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n");
|
||||
} else if (doSpline) {
|
||||
WRITE(p, " int2 spline_num_patches = int2(u_spline_count_u - 3, u_spline_count_v - 3);\n");
|
||||
WRITE(p, " int2 spline_type = int2(u_spline_type_u, u_spline_type_v);\n");
|
||||
WRITE(p, " float2 knots[6];\n");
|
||||
WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n");
|
||||
WRITE(p, " spline_weight(tess_pos + patch_pos, knots, weights);\n");
|
||||
}
|
||||
WRITE(p, " float3 pos = tess_sample(_pos, weights);\n");
|
||||
if (doTexture && hasTexcoord) {
|
||||
if (hasTexcoordTess)
|
||||
WRITE(p, " float2 tex = tess_sample(_tex, weights);\n");
|
||||
else
|
||||
WRITE(p, " float2 tex = tess_pos + patch_pos;\n");
|
||||
}
|
||||
if (hasColor) {
|
||||
if (hasColorTess)
|
||||
WRITE(p, " float4 col = tess_sample(_col, weights);\n");
|
||||
else
|
||||
WRITE(p, " float4 col = u_tess_col_tex.Load(int2(0, 0)).rgba;\n");
|
||||
}
|
||||
if (hasNormal) {
|
||||
// Curved surface is probably always need to compute normal(not sampling from control points)
|
||||
WRITE(p, " float2 weights[4];\n");
|
||||
if (doBezier) {
|
||||
// Bernstein derivative
|
||||
WRITE(p, " float2 bernderiv[4];\n");
|
||||
WRITE(p, " bernderiv[0] = -3.0 * (tess_pos - 1.0) * (tess_pos - 1.0); \n");
|
||||
WRITE(p, " bernderiv[1] = 9.0 * tess_pos * tess_pos - 12.0 * tess_pos + 3.0; \n");
|
||||
WRITE(p, " bernderiv[2] = 3.0 * (2.0 - 3.0 * tess_pos) * tess_pos; \n");
|
||||
WRITE(p, " bernderiv[3] = 3.0 * tess_pos * tess_pos; \n");
|
||||
|
||||
WRITE(p, " float2 bernderiv_u[4];\n");
|
||||
WRITE(p, " float2 bernderiv_v[4];\n");
|
||||
WRITE(p, " for (int i = 0; i < 4; i++) {\n");
|
||||
WRITE(p, " bernderiv_u[i] = float2(bernderiv[i].x, weights[i].y);\n");
|
||||
WRITE(p, " bernderiv_v[i] = float2(weights[i].x, bernderiv[i].y);\n");
|
||||
WRITE(p, " }\n");
|
||||
|
||||
WRITE(p, " float3 du = tess_sample(_pos, bernderiv_u);\n");
|
||||
WRITE(p, " float3 dv = tess_sample(_pos, bernderiv_v);\n");
|
||||
// Bernstein 3D
|
||||
WRITE(p, " weights[0] = (1.0 - tess_pos) * (1.0 - tess_pos) * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[1] = 3.0 * tess_pos * (1.0 - tess_pos) * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[2] = 3.0 * tess_pos * tess_pos * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n");
|
||||
} else if (doSpline) {
|
||||
WRITE(p, " float2 tess_next_u = float2(In.normal.x, 0.0);\n");
|
||||
WRITE(p, " float2 tess_next_v = float2(0.0, In.normal.y);\n");
|
||||
// Right
|
||||
WRITE(p, " float2 tess_pos_r = tess_pos + tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_r + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " float3 pos_r = tess_sample(_pos, weights);\n");
|
||||
// Left
|
||||
WRITE(p, " float2 tess_pos_l = tess_pos - tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_l + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " float3 pos_l = tess_sample(_pos, weights);\n");
|
||||
// Down
|
||||
WRITE(p, " float2 tess_pos_d = tess_pos + tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_d + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " float3 pos_d = tess_sample(_pos, weights);\n");
|
||||
// Up
|
||||
WRITE(p, " float2 tess_pos_u = tess_pos - tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_u + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " float3 pos_u = tess_sample(_pos, weights);\n");
|
||||
|
||||
WRITE(p, " float3 du = pos_r - pos_l;\n");
|
||||
WRITE(p, " float3 dv = pos_d - pos_u;\n");
|
||||
WRITE(p, " int2 spline_num_patches = int2(u_spline_count_u - 3, u_spline_count_v - 3);\n");
|
||||
WRITE(p, " int2 spline_type = int2(u_spline_type_u, u_spline_type_v);\n");
|
||||
WRITE(p, " float2 knots[6];\n");
|
||||
WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n");
|
||||
WRITE(p, " spline_weight(tess_pos + patch_pos, knots, weights);\n");
|
||||
}
|
||||
WRITE(p, " float3 nrm = cross(du, dv);\n");
|
||||
WRITE(p, " nrm = normalize(nrm);\n");
|
||||
WRITE(p, " float3 pos = tess_sample(_pos, weights);\n");
|
||||
if (doTexture && hasTexcoord) {
|
||||
if (hasTexcoordTess)
|
||||
WRITE(p, " float2 tex = tess_sample(_tex, weights);\n");
|
||||
else
|
||||
WRITE(p, " float2 tex = tess_pos + patch_pos;\n");
|
||||
}
|
||||
if (hasColor) {
|
||||
if (hasColorTess)
|
||||
WRITE(p, " float4 col = tess_sample(_col, weights);\n");
|
||||
else
|
||||
WRITE(p, " float4 col = u_tess_col_tex.Load(int2(0, 0)).rgba;\n");
|
||||
}
|
||||
if (hasNormal) {
|
||||
// Curved surface is probably always need to compute normal(not sampling from control points)
|
||||
if (doBezier) {
|
||||
// Bernstein derivative
|
||||
WRITE(p, " float2 bernderiv[4];\n");
|
||||
WRITE(p, " bernderiv[0] = -3.0 * (tess_pos - 1.0) * (tess_pos - 1.0); \n");
|
||||
WRITE(p, " bernderiv[1] = 9.0 * tess_pos * tess_pos - 12.0 * tess_pos + 3.0; \n");
|
||||
WRITE(p, " bernderiv[2] = 3.0 * (2.0 - 3.0 * tess_pos) * tess_pos; \n");
|
||||
WRITE(p, " bernderiv[3] = 3.0 * tess_pos * tess_pos; \n");
|
||||
|
||||
WRITE(p, " float2 bernderiv_u[4];\n");
|
||||
WRITE(p, " float2 bernderiv_v[4];\n");
|
||||
WRITE(p, " for (int i = 0; i < 4; i++) {\n");
|
||||
WRITE(p, " bernderiv_u[i] = float2(bernderiv[i].x, weights[i].y);\n");
|
||||
WRITE(p, " bernderiv_v[i] = float2(weights[i].x, bernderiv[i].y);\n");
|
||||
WRITE(p, " }\n");
|
||||
|
||||
WRITE(p, " float3 du = tess_sample(_pos, bernderiv_u);\n");
|
||||
WRITE(p, " float3 dv = tess_sample(_pos, bernderiv_v);\n");
|
||||
} else if (doSpline) {
|
||||
WRITE(p, " float2 tess_next_u = float2(In.normal.x, 0.0);\n");
|
||||
WRITE(p, " float2 tess_next_v = float2(0.0, In.normal.y);\n");
|
||||
// Right
|
||||
WRITE(p, " float2 tess_pos_r = tess_pos + tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_r + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " float3 pos_r = tess_sample(_pos, weights);\n");
|
||||
// Left
|
||||
WRITE(p, " float2 tess_pos_l = tess_pos - tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_l + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " float3 pos_l = tess_sample(_pos, weights);\n");
|
||||
// Down
|
||||
WRITE(p, " float2 tess_pos_d = tess_pos + tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_d + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " float3 pos_d = tess_sample(_pos, weights);\n");
|
||||
// Up
|
||||
WRITE(p, " float2 tess_pos_u = tess_pos - tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_u + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " float3 pos_u = tess_sample(_pos, weights);\n");
|
||||
|
||||
WRITE(p, " float3 du = pos_r - pos_l;\n");
|
||||
WRITE(p, " float3 dv = pos_d - pos_u;\n");
|
||||
}
|
||||
WRITE(p, " float3 nrm = cross(du, dv);\n");
|
||||
WRITE(p, " nrm = normalize(nrm);\n");
|
||||
}
|
||||
WRITE(p, " float3 worldpos = mul(float4(pos.xyz, 1.0), u_world);\n");
|
||||
if (hasNormal)
|
||||
WRITE(p, " float3 worldnormal = normalize(mul(float4(%snrm, 0.0), u_world));\n", flipNormalTess ? "-" : "");
|
||||
else
|
||||
WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n");
|
||||
} else {
|
||||
// No skinning, just standard T&L.
|
||||
WRITE(p, " float3 worldpos = mul(float4(In.position.xyz, 1.0), u_world);\n");
|
||||
if (hasNormal)
|
||||
WRITE(p, " float3 worldnormal = normalize(mul(float4(%sIn.normal, 0.0), u_world));\n", flipNormal ? "-" : "");
|
||||
else
|
||||
WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n");
|
||||
}
|
||||
WRITE(p, " float3 worldpos = mul(float4(pos.xyz, 1.0), u_world);\n");
|
||||
if (hasNormal)
|
||||
WRITE(p, " float3 worldnormal = normalize(mul(float4(%snrm, 0.0), u_world));\n", flipNormalTess ? "-" : "");
|
||||
else
|
||||
WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n");
|
||||
} else {
|
||||
WRITE(p, " float3 worldpos = mul(float4(In.position.xyz, 1.0), u_world);\n");
|
||||
if (hasNormal)
|
||||
WRITE(p, " float3 worldnormal = normalize(mul(float4(%sIn.normal, 0.0), u_world));\n", flipNormal ? "-" : "");
|
||||
else
|
||||
WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n");
|
||||
}
|
||||
|
||||
WRITE(p, " float4 viewPos = float4(mul(float4(worldpos, 1.0), u_view), 1.0);\n");
|
||||
|
|
|
@ -324,7 +324,7 @@ void DrawEngineGLES::DoFlush() {
|
|||
|
||||
// Cannot cache vertex data with morph enabled.
|
||||
bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK);
|
||||
// Also avoid caching when skinning.
|
||||
// Also avoid caching when software skinning.
|
||||
if (lastVType_ & GE_VTYPE_WEIGHT_MASK)
|
||||
useCache = false;
|
||||
|
||||
|
@ -470,7 +470,7 @@ void DrawEngineGLES::DoFlush() {
|
|||
vai->lastFrame = gpuStats.numFlips;
|
||||
} else {
|
||||
if (lastVType_ & GE_VTYPE_WEIGHT_MASK) {
|
||||
// If skinning, we've already predecoded into "decoded". So push that content.
|
||||
// If software skinning, we've already predecoded into "decoded". So push that content.
|
||||
size_t size = decodedVerts_ * dec_->GetDecVtxFmt().stride;
|
||||
u8 *dest = (u8 *)frameData.pushVertex->Push(size, &vertexBufferOffset, &vertexBuffer);
|
||||
memcpy(dest, decoded, size);
|
||||
|
|
|
@ -435,111 +435,114 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// Step 1: World Transform
|
||||
// Hardware tessellation
|
||||
if (doBezier || doSpline) {
|
||||
WRITE(p, " vec3 _pos[16];\n");
|
||||
WRITE(p, " vec2 _tex[16];\n");
|
||||
WRITE(p, " vec4 _col[16];\n");
|
||||
WRITE(p, " int num_patches_u = %s;\n", doBezier ? "(u_spline_count_u - 1) / 3" : "u_spline_count_u - 3");
|
||||
WRITE(p, " int u = int(mod(float(gl_InstanceID), float(num_patches_u)));\n");
|
||||
WRITE(p, " int v = gl_InstanceID / num_patches_u;\n");
|
||||
WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n");
|
||||
WRITE(p, " for (int i = 0; i < 4; i++) {\n");
|
||||
WRITE(p, " for (int j = 0; j < 4; j++) {\n");
|
||||
WRITE(p, " int index = (i + v%s) * u_spline_count_u + (j + u%s);\n", doBezier ? " * 3" : "", doBezier ? " * 3" : "");
|
||||
WRITE(p, " _pos[i * 4 + j] = %s(u_tess_pos_tex, ivec2(index, 0), 0).xyz;\n", texelFetch);
|
||||
if (doTexture && hasTexcoord && hasTexcoordTess)
|
||||
WRITE(p, " _tex[i * 4 + j] = %s(u_tess_tex_tex, ivec2(index, 0), 0).xy;\n", texelFetch);
|
||||
if (hasColor && hasColorTess)
|
||||
WRITE(p, " _col[i * 4 + j] = %s(u_tess_col_tex, ivec2(index, 0), 0).rgba;\n", texelFetch);
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " vec2 tess_pos = position.xy;\n");
|
||||
WRITE(p, " vec2 weights[4];\n");
|
||||
if (doBezier) {
|
||||
// Bernstein 3D
|
||||
WRITE(p, " weights[0] = (1.0 - tess_pos) * (1.0 - tess_pos) * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[1] = 3.0 * tess_pos * (1.0 - tess_pos) * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[2] = 3.0 * tess_pos * tess_pos * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n");
|
||||
} else { // Spline
|
||||
WRITE(p, " ivec2 spline_num_patches = ivec2(u_spline_count_u - 3, u_spline_count_v - 3);\n");
|
||||
WRITE(p, " ivec2 spline_type = ivec2(u_spline_type_u, u_spline_type_v);\n");
|
||||
WRITE(p, " vec2 knots[6];\n");
|
||||
WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n");
|
||||
WRITE(p, " spline_weight(tess_pos + vec2(patch_pos), knots, weights);\n");
|
||||
}
|
||||
WRITE(p, " vec3 pos = tess_sample(_pos, weights);\n");
|
||||
if (doTexture && hasTexcoord) {
|
||||
if (hasTexcoordTess)
|
||||
WRITE(p, " vec2 tex = tess_sample(_tex, weights);\n");
|
||||
else
|
||||
WRITE(p, " vec2 tex = tess_pos + vec2(patch_pos);\n");
|
||||
}
|
||||
if (hasColor) {
|
||||
if (hasColorTess)
|
||||
WRITE(p, " vec4 col = tess_sample(_col, weights);\n");
|
||||
else
|
||||
WRITE(p, " vec4 col = %s(u_tess_col_tex, ivec2(0, 0), 0).rgba;\n", texelFetch);
|
||||
}
|
||||
if (hasNormal) {
|
||||
// Curved surface is probably always need to compute normal(not sampling from control points)
|
||||
// Step 1: World Transform / Skinning
|
||||
if (true) {
|
||||
// Hardware tessellation
|
||||
if (doBezier || doSpline) {
|
||||
WRITE(p, " vec3 _pos[16];\n");
|
||||
WRITE(p, " vec2 _tex[16];\n");
|
||||
WRITE(p, " vec4 _col[16];\n");
|
||||
WRITE(p, " int num_patches_u = %s;\n", doBezier ? "(u_spline_count_u - 1) / 3" : "u_spline_count_u - 3");
|
||||
WRITE(p, " int u = int(mod(float(gl_InstanceID), float(num_patches_u)));\n");
|
||||
WRITE(p, " int v = gl_InstanceID / num_patches_u;\n");
|
||||
WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n");
|
||||
WRITE(p, " for (int i = 0; i < 4; i++) {\n");
|
||||
WRITE(p, " for (int j = 0; j < 4; j++) {\n");
|
||||
WRITE(p, " int index = (i + v%s) * u_spline_count_u + (j + u%s);\n", doBezier ? " * 3" : "", doBezier ? " * 3" : "");
|
||||
WRITE(p, " _pos[i * 4 + j] = %s(u_tess_pos_tex, ivec2(index, 0), 0).xyz;\n", texelFetch);
|
||||
if (doTexture && hasTexcoord && hasTexcoordTess)
|
||||
WRITE(p, " _tex[i * 4 + j] = %s(u_tess_tex_tex, ivec2(index, 0), 0).xy;\n", texelFetch);
|
||||
if (hasColor && hasColorTess)
|
||||
WRITE(p, " _col[i * 4 + j] = %s(u_tess_col_tex, ivec2(index, 0), 0).rgba;\n", texelFetch);
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " vec2 tess_pos = position.xy;\n");
|
||||
WRITE(p, " vec2 weights[4];\n");
|
||||
if (doBezier) {
|
||||
// Bernstein derivative
|
||||
WRITE(p, " vec2 bernderiv[4];\n");
|
||||
WRITE(p, " bernderiv[0] = -3.0 * (tess_pos - 1.0) * (tess_pos - 1.0); \n");
|
||||
WRITE(p, " bernderiv[1] = 9.0 * tess_pos * tess_pos - 12.0 * tess_pos + 3.0; \n");
|
||||
WRITE(p, " bernderiv[2] = 3.0 * (2.0 - 3.0 * tess_pos) * tess_pos; \n");
|
||||
WRITE(p, " bernderiv[3] = 3.0 * tess_pos * tess_pos; \n");
|
||||
|
||||
WRITE(p, " vec2 bernderiv_u[4];\n");
|
||||
WRITE(p, " vec2 bernderiv_v[4];\n");
|
||||
WRITE(p, " for (int i = 0; i < 4; i++) {\n");
|
||||
WRITE(p, " bernderiv_u[i] = vec2(bernderiv[i].x, weights[i].y);\n");
|
||||
WRITE(p, " bernderiv_v[i] = vec2(weights[i].x, bernderiv[i].y);\n");
|
||||
WRITE(p, " }\n");
|
||||
|
||||
WRITE(p, " vec3 du = tess_sample(_pos, bernderiv_u);\n");
|
||||
WRITE(p, " vec3 dv = tess_sample(_pos, bernderiv_v);\n");
|
||||
// Bernstein 3D
|
||||
WRITE(p, " weights[0] = (1.0 - tess_pos) * (1.0 - tess_pos) * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[1] = 3.0 * tess_pos * (1.0 - tess_pos) * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[2] = 3.0 * tess_pos * tess_pos * (1.0 - tess_pos);\n");
|
||||
WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n");
|
||||
} else { // Spline
|
||||
WRITE(p, " vec2 tess_next_u = vec2(normal.x, 0.0);\n");
|
||||
WRITE(p, " vec2 tess_next_v = vec2(0.0, normal.y);\n");
|
||||
// Right
|
||||
WRITE(p, " vec2 tess_pos_r = tess_pos + tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_r + vec2(patch_pos), knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_r = tess_sample(_pos, weights);\n");
|
||||
// Left
|
||||
WRITE(p, " vec2 tess_pos_l = tess_pos - tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_l + vec2(patch_pos), knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_l = tess_sample(_pos, weights);\n");
|
||||
// Down
|
||||
WRITE(p, " vec2 tess_pos_d = tess_pos + tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_d + vec2(patch_pos), knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_d = tess_sample(_pos, weights);\n");
|
||||
// Up
|
||||
WRITE(p, " vec2 tess_pos_u = tess_pos - tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_u + vec2(patch_pos), knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_u = tess_sample(_pos, weights);\n");
|
||||
|
||||
WRITE(p, " vec3 du = pos_r - pos_l;\n");
|
||||
WRITE(p, " vec3 dv = pos_d - pos_u;\n");
|
||||
WRITE(p, " ivec2 spline_num_patches = ivec2(u_spline_count_u - 3, u_spline_count_v - 3);\n");
|
||||
WRITE(p, " ivec2 spline_type = ivec2(u_spline_type_u, u_spline_type_v);\n");
|
||||
WRITE(p, " vec2 knots[6];\n");
|
||||
WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n");
|
||||
WRITE(p, " spline_weight(tess_pos + vec2(patch_pos), knots, weights);\n");
|
||||
}
|
||||
WRITE(p, " vec3 pos = tess_sample(_pos, weights);\n");
|
||||
if (doTexture && hasTexcoord) {
|
||||
if (hasTexcoordTess)
|
||||
WRITE(p, " vec2 tex = tess_sample(_tex, weights);\n");
|
||||
else
|
||||
WRITE(p, " vec2 tex = tess_pos + vec2(patch_pos);\n");
|
||||
}
|
||||
if (hasColor) {
|
||||
if (hasColorTess)
|
||||
WRITE(p, " vec4 col = tess_sample(_col, weights);\n");
|
||||
else
|
||||
WRITE(p, " vec4 col = %s(u_tess_col_tex, ivec2(0, 0), 0).rgba;\n", texelFetch);
|
||||
}
|
||||
if (hasNormal) {
|
||||
// Curved surface is probably always need to compute normal(not sampling from control points)
|
||||
if (doBezier) {
|
||||
// Bernstein derivative
|
||||
WRITE(p, " vec2 bernderiv[4];\n");
|
||||
WRITE(p, " bernderiv[0] = -3.0 * (tess_pos - 1.0) * (tess_pos - 1.0); \n");
|
||||
WRITE(p, " bernderiv[1] = 9.0 * tess_pos * tess_pos - 12.0 * tess_pos + 3.0; \n");
|
||||
WRITE(p, " bernderiv[2] = 3.0 * (2.0 - 3.0 * tess_pos) * tess_pos; \n");
|
||||
WRITE(p, " bernderiv[3] = 3.0 * tess_pos * tess_pos; \n");
|
||||
|
||||
WRITE(p, " vec2 bernderiv_u[4];\n");
|
||||
WRITE(p, " vec2 bernderiv_v[4];\n");
|
||||
WRITE(p, " for (int i = 0; i < 4; i++) {\n");
|
||||
WRITE(p, " bernderiv_u[i] = vec2(bernderiv[i].x, weights[i].y);\n");
|
||||
WRITE(p, " bernderiv_v[i] = vec2(weights[i].x, bernderiv[i].y);\n");
|
||||
WRITE(p, " }\n");
|
||||
|
||||
WRITE(p, " vec3 du = tess_sample(_pos, bernderiv_u);\n");
|
||||
WRITE(p, " vec3 dv = tess_sample(_pos, bernderiv_v);\n");
|
||||
} else { // Spline
|
||||
WRITE(p, " vec2 tess_next_u = vec2(normal.x, 0.0);\n");
|
||||
WRITE(p, " vec2 tess_next_v = vec2(0.0, normal.y);\n");
|
||||
// Right
|
||||
WRITE(p, " vec2 tess_pos_r = tess_pos + tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_r + vec2(patch_pos), knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_r = tess_sample(_pos, weights);\n");
|
||||
// Left
|
||||
WRITE(p, " vec2 tess_pos_l = tess_pos - tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_l + vec2(patch_pos), knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_l = tess_sample(_pos, weights);\n");
|
||||
// Down
|
||||
WRITE(p, " vec2 tess_pos_d = tess_pos + tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_d + vec2(patch_pos), knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_d = tess_sample(_pos, weights);\n");
|
||||
// Up
|
||||
WRITE(p, " vec2 tess_pos_u = tess_pos - tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_u + vec2(patch_pos), knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_u = tess_sample(_pos, weights);\n");
|
||||
|
||||
WRITE(p, " vec3 du = pos_r - pos_l;\n");
|
||||
WRITE(p, " vec3 dv = pos_d - pos_u;\n");
|
||||
}
|
||||
WRITE(p, " vec3 nrm = cross(du, dv);\n");
|
||||
WRITE(p, " nrm = normalize(nrm);\n");
|
||||
}
|
||||
WRITE(p, " vec3 worldpos = (u_world * vec4(pos.xyz, 1.0)).xyz;\n");
|
||||
if (hasNormal) {
|
||||
WRITE(p, " mediump vec3 worldnormal = normalize((u_world * vec4(%snrm, 0.0)).xyz);\n", flipNormalTess ? "-" : "");
|
||||
} else {
|
||||
WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n");
|
||||
}
|
||||
WRITE(p, " vec3 nrm = cross(du, dv);\n");
|
||||
WRITE(p, " nrm = normalize(nrm);\n");
|
||||
}
|
||||
WRITE(p, " vec3 worldpos = (u_world * vec4(pos.xyz, 1.0)).xyz;\n");
|
||||
if (hasNormal) {
|
||||
WRITE(p, " mediump vec3 worldnormal = normalize((u_world * vec4(%snrm, 0.0)).xyz);\n", flipNormalTess ? "-" : "");
|
||||
} else {
|
||||
WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n");
|
||||
// No skinning, just standard T&L.
|
||||
WRITE(p, " vec3 worldpos = (u_world * vec4(position.xyz, 1.0)).xyz;\n");
|
||||
if (hasNormal)
|
||||
WRITE(p, " mediump vec3 worldnormal = normalize((u_world * vec4(%snormal, 0.0)).xyz);\n", flipNormal ? "-" : "");
|
||||
else
|
||||
WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n");
|
||||
}
|
||||
} else {
|
||||
WRITE(p, " vec3 worldpos = (u_world * vec4(position.xyz, 1.0)).xyz;\n");
|
||||
if (hasNormal)
|
||||
WRITE(p, " mediump vec3 worldnormal = normalize((u_world * vec4(%snormal, 0.0)).xyz);\n", flipNormal ? "-" : "");
|
||||
else
|
||||
WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n");
|
||||
}
|
||||
|
||||
WRITE(p, " vec4 viewPos = u_view * vec4(worldpos, 1.0);\n");
|
||||
|
|
|
@ -585,7 +585,7 @@ void DrawEngineVulkan::DoFlush() {
|
|||
|
||||
// Cannot cache vertex data with morph enabled.
|
||||
bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK);
|
||||
// Also avoid caching when skinning.
|
||||
// Also avoid caching when software skinning.
|
||||
VkBuffer vbuf = VK_NULL_HANDLE;
|
||||
VkBuffer ibuf = VK_NULL_HANDLE;
|
||||
if (lastVType_ & GE_VTYPE_WEIGHT_MASK) {
|
||||
|
@ -731,7 +731,7 @@ void DrawEngineVulkan::DoFlush() {
|
|||
}
|
||||
} else {
|
||||
if (lastVType_ & GE_VTYPE_WEIGHT_MASK) {
|
||||
// If skinning, we've already predecoded into "decoded". So push that content.
|
||||
// If software skinning, we've already predecoded into "decoded". So push that content.
|
||||
VkDeviceSize size = decodedVerts_ * dec_->GetDecVtxFmt().stride;
|
||||
u8 *dest = (u8 *)frame->pushVertex->Push(size, &vbOffset, &vbuf);
|
||||
memcpy(dest, decoded, size);
|
||||
|
|
|
@ -307,109 +307,112 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer) {
|
|||
}
|
||||
} else {
|
||||
// Step 1: World Transform / Skinning
|
||||
if (doBezier || doSpline) {
|
||||
WRITE(p, " vec3 _pos[16];\n");
|
||||
WRITE(p, " vec2 _tex[16];\n");
|
||||
WRITE(p, " vec4 _col[16];\n");
|
||||
WRITE(p, " int num_patches_u = %s;\n", doBezier ? "(base.spline_count_u - 1) / 3" : "base.spline_count_u - 3");
|
||||
WRITE(p, " int u = int(mod(gl_InstanceIndex, num_patches_u));\n");
|
||||
WRITE(p, " int v = gl_InstanceIndex / num_patches_u;\n");
|
||||
WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n");
|
||||
WRITE(p, " for (int i = 0; i < 4; i++) {\n");
|
||||
WRITE(p, " for (int j = 0; j < 4; j++) {\n");
|
||||
WRITE(p, " int idx = (i + v%s) * base.spline_count_u + (j + u%s);\n", doBezier ? " * 3" : "", doBezier ? " * 3" : "");
|
||||
WRITE(p, " _pos[i * 4 + j] = tess_data.data[idx].pos.xyz;\n");
|
||||
if (doTexture && hasTexcoord && hasTexcoordTess)
|
||||
WRITE(p, " _tex[i * 4 + j] = tess_data.data[idx].uv.xy;\n");
|
||||
if (hasColor && hasColorTess)
|
||||
WRITE(p, " _col[i * 4 + j] = tess_data.data[idx].color;\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " vec2 tess_pos = position.xy;\n");
|
||||
WRITE(p, " vec2 weights[4];\n");
|
||||
if (doBezier) {
|
||||
// Bernstein 3D
|
||||
WRITE(p, " weights[0] = (1 - tess_pos) * (1 - tess_pos) * (1 - tess_pos);\n");
|
||||
WRITE(p, " weights[1] = 3 * tess_pos * (1 - tess_pos) * (1 - tess_pos);\n");
|
||||
WRITE(p, " weights[2] = 3 * tess_pos * tess_pos * (1 - tess_pos);\n");
|
||||
WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n");
|
||||
} else { // Spline
|
||||
WRITE(p, " ivec2 spline_num_patches = ivec2(base.spline_count_u - 3, base.spline_count_v - 3);\n");
|
||||
WRITE(p, " ivec2 spline_type = ivec2(base.spline_type_u, base.spline_type_v);\n");
|
||||
WRITE(p, " vec2 knots[6];\n");
|
||||
WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n");
|
||||
WRITE(p, " spline_weight(tess_pos + patch_pos, knots, weights);\n");
|
||||
}
|
||||
WRITE(p, " vec3 pos = tess_sample(_pos, weights);\n");
|
||||
if (doTexture && hasTexcoord) {
|
||||
if (hasTexcoordTess)
|
||||
WRITE(p, " vec2 tex = tess_sample(_tex, weights);\n");
|
||||
else
|
||||
WRITE(p, " vec2 tex = tess_pos + patch_pos;\n");
|
||||
}
|
||||
if (hasColor) {
|
||||
if (hasColorTess)
|
||||
WRITE(p, " vec4 col = tess_sample(_col, weights);\n");
|
||||
else
|
||||
WRITE(p, " vec4 col = tess_data.data[0].color;\n");
|
||||
}
|
||||
if (hasNormal) {
|
||||
// Curved surface is probably always need to compute normal(not sampling from control points)
|
||||
if (true) {
|
||||
if (doBezier || doSpline) {
|
||||
WRITE(p, " vec3 _pos[16];\n");
|
||||
WRITE(p, " vec2 _tex[16];\n");
|
||||
WRITE(p, " vec4 _col[16];\n");
|
||||
WRITE(p, " int num_patches_u = %s;\n", doBezier ? "(base.spline_count_u - 1) / 3" : "base.spline_count_u - 3");
|
||||
WRITE(p, " int u = int(mod(gl_InstanceIndex, num_patches_u));\n");
|
||||
WRITE(p, " int v = gl_InstanceIndex / num_patches_u;\n");
|
||||
WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n");
|
||||
WRITE(p, " for (int i = 0; i < 4; i++) {\n");
|
||||
WRITE(p, " for (int j = 0; j < 4; j++) {\n");
|
||||
WRITE(p, " int idx = (i + v%s) * base.spline_count_u + (j + u%s);\n", doBezier ? " * 3" : "", doBezier ? " * 3" : "");
|
||||
WRITE(p, " _pos[i * 4 + j] = tess_data.data[idx].pos.xyz;\n");
|
||||
if (doTexture && hasTexcoord && hasTexcoordTess)
|
||||
WRITE(p, " _tex[i * 4 + j] = tess_data.data[idx].uv.xy;\n");
|
||||
if (hasColor && hasColorTess)
|
||||
WRITE(p, " _col[i * 4 + j] = tess_data.data[idx].color;\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " vec2 tess_pos = position.xy;\n");
|
||||
WRITE(p, " vec2 weights[4];\n");
|
||||
if (doBezier) {
|
||||
// Bernstein derivative
|
||||
WRITE(p, " vec2 bernderiv[4];\n");
|
||||
WRITE(p, " bernderiv[0] = -3 * (tess_pos - 1) * (tess_pos - 1); \n");
|
||||
WRITE(p, " bernderiv[1] = 9 * tess_pos * tess_pos - 12 * tess_pos + 3; \n");
|
||||
WRITE(p, " bernderiv[2] = 3 * (2 - 3 * tess_pos) * tess_pos; \n");
|
||||
WRITE(p, " bernderiv[3] = 3 * tess_pos * tess_pos; \n");
|
||||
|
||||
WRITE(p, " vec2 bernderiv_u[4];\n");
|
||||
WRITE(p, " vec2 bernderiv_v[4];\n");
|
||||
WRITE(p, " for (int i = 0; i < 4; i++) {\n");
|
||||
WRITE(p, " bernderiv_u[i] = vec2(bernderiv[i].x, weights[i].y);\n");
|
||||
WRITE(p, " bernderiv_v[i] = vec2(weights[i].x, bernderiv[i].y);\n");
|
||||
WRITE(p, " }\n");
|
||||
|
||||
WRITE(p, " vec3 du = tess_sample(_pos, bernderiv_u);\n");
|
||||
WRITE(p, " vec3 dv = tess_sample(_pos, bernderiv_v);\n");
|
||||
// Bernstein 3D
|
||||
WRITE(p, " weights[0] = (1 - tess_pos) * (1 - tess_pos) * (1 - tess_pos);\n");
|
||||
WRITE(p, " weights[1] = 3 * tess_pos * (1 - tess_pos) * (1 - tess_pos);\n");
|
||||
WRITE(p, " weights[2] = 3 * tess_pos * tess_pos * (1 - tess_pos);\n");
|
||||
WRITE(p, " weights[3] = tess_pos * tess_pos * tess_pos;\n");
|
||||
} else { // Spline
|
||||
WRITE(p, " vec2 tess_next_u = vec2(normal.x, 0);\n");
|
||||
WRITE(p, " vec2 tess_next_v = vec2(0, normal.y);\n");
|
||||
// Right
|
||||
WRITE(p, " vec2 tess_pos_r = tess_pos + tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_r + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_r = tess_sample(_pos, weights);\n");
|
||||
// Left
|
||||
WRITE(p, " vec2 tess_pos_l = tess_pos - tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_l + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_l = tess_sample(_pos, weights);\n");
|
||||
// Down
|
||||
WRITE(p, " vec2 tess_pos_d = tess_pos + tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_d + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_d = tess_sample(_pos, weights);\n");
|
||||
// Up
|
||||
WRITE(p, " vec2 tess_pos_u = tess_pos - tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_u + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_u = tess_sample(_pos, weights);\n");
|
||||
|
||||
WRITE(p, " vec3 du = pos_r - pos_l;\n");
|
||||
WRITE(p, " vec3 dv = pos_d - pos_u;\n");
|
||||
WRITE(p, " ivec2 spline_num_patches = ivec2(base.spline_count_u - 3, base.spline_count_v - 3);\n");
|
||||
WRITE(p, " ivec2 spline_type = ivec2(base.spline_type_u, base.spline_type_v);\n");
|
||||
WRITE(p, " vec2 knots[6];\n");
|
||||
WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n");
|
||||
WRITE(p, " spline_weight(tess_pos + patch_pos, knots, weights);\n");
|
||||
}
|
||||
WRITE(p, " vec3 pos = tess_sample(_pos, weights);\n");
|
||||
if (doTexture && hasTexcoord) {
|
||||
if (hasTexcoordTess)
|
||||
WRITE(p, " vec2 tex = tess_sample(_tex, weights);\n");
|
||||
else
|
||||
WRITE(p, " vec2 tex = tess_pos + patch_pos;\n");
|
||||
}
|
||||
if (hasColor) {
|
||||
if (hasColorTess)
|
||||
WRITE(p, " vec4 col = tess_sample(_col, weights);\n");
|
||||
else
|
||||
WRITE(p, " vec4 col = tess_data.data[0].color;\n");
|
||||
}
|
||||
if (hasNormal) {
|
||||
// Curved surface is probably always need to compute normal(not sampling from control points)
|
||||
if (doBezier) {
|
||||
// Bernstein derivative
|
||||
WRITE(p, " vec2 bernderiv[4];\n");
|
||||
WRITE(p, " bernderiv[0] = -3 * (tess_pos - 1) * (tess_pos - 1); \n");
|
||||
WRITE(p, " bernderiv[1] = 9 * tess_pos * tess_pos - 12 * tess_pos + 3; \n");
|
||||
WRITE(p, " bernderiv[2] = 3 * (2 - 3 * tess_pos) * tess_pos; \n");
|
||||
WRITE(p, " bernderiv[3] = 3 * tess_pos * tess_pos; \n");
|
||||
|
||||
WRITE(p, " vec2 bernderiv_u[4];\n");
|
||||
WRITE(p, " vec2 bernderiv_v[4];\n");
|
||||
WRITE(p, " for (int i = 0; i < 4; i++) {\n");
|
||||
WRITE(p, " bernderiv_u[i] = vec2(bernderiv[i].x, weights[i].y);\n");
|
||||
WRITE(p, " bernderiv_v[i] = vec2(weights[i].x, bernderiv[i].y);\n");
|
||||
WRITE(p, " }\n");
|
||||
|
||||
WRITE(p, " vec3 du = tess_sample(_pos, bernderiv_u);\n");
|
||||
WRITE(p, " vec3 dv = tess_sample(_pos, bernderiv_v);\n");
|
||||
} else { // Spline
|
||||
WRITE(p, " vec2 tess_next_u = vec2(normal.x, 0);\n");
|
||||
WRITE(p, " vec2 tess_next_v = vec2(0, normal.y);\n");
|
||||
// Right
|
||||
WRITE(p, " vec2 tess_pos_r = tess_pos + tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_r + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_r = tess_sample(_pos, weights);\n");
|
||||
// Left
|
||||
WRITE(p, " vec2 tess_pos_l = tess_pos - tess_next_u;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_l + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_l = tess_sample(_pos, weights);\n");
|
||||
// Down
|
||||
WRITE(p, " vec2 tess_pos_d = tess_pos + tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_d + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_d = tess_sample(_pos, weights);\n");
|
||||
// Up
|
||||
WRITE(p, " vec2 tess_pos_u = tess_pos - tess_next_v;\n");
|
||||
WRITE(p, " spline_weight(tess_pos_u + patch_pos, knots, weights);\n");
|
||||
WRITE(p, " vec3 pos_u = tess_sample(_pos, weights);\n");
|
||||
|
||||
WRITE(p, " vec3 du = pos_r - pos_l;\n");
|
||||
WRITE(p, " vec3 dv = pos_d - pos_u;\n");
|
||||
}
|
||||
WRITE(p, " vec3 nrm = cross(du, dv);\n");
|
||||
WRITE(p, " nrm = normalize(nrm);\n");
|
||||
}
|
||||
WRITE(p, " vec3 worldpos = vec4(pos.xyz, 1.0) * base.world_mtx;\n");
|
||||
if (hasNormal) {
|
||||
WRITE(p, " mediump vec3 worldnormal = normalize(vec4(%snrm, 0.0) * base.world_mtx);\n", flipNormalTess ? "-" : "");
|
||||
} else {
|
||||
WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n");
|
||||
}
|
||||
WRITE(p, " vec3 nrm = cross(du, dv);\n");
|
||||
WRITE(p, " nrm = normalize(nrm);\n");
|
||||
}
|
||||
WRITE(p, " vec3 worldpos = vec4(pos.xyz, 1.0) * base.world_mtx;\n");
|
||||
if (hasNormal) {
|
||||
WRITE(p, " mediump vec3 worldnormal = normalize(vec4(%snrm, 0.0) * base.world_mtx);\n", flipNormalTess ? "-" : "");
|
||||
} else {
|
||||
WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n");
|
||||
// No skinning, just standard T&L.
|
||||
WRITE(p, " vec3 worldpos = vec4(position.xyz, 1.0) * base.world_mtx;\n");
|
||||
if (hasNormal)
|
||||
WRITE(p, " mediump vec3 worldnormal = normalize(vec4(%snormal, 0.0) * base.world_mtx);\n", flipNormal ? "-" : "");
|
||||
else
|
||||
WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n");
|
||||
}
|
||||
} else {
|
||||
WRITE(p, " vec3 worldpos = vec4(position.xyz, 1.0) * base.world_mtx;\n");
|
||||
if (hasNormal)
|
||||
WRITE(p, " mediump vec3 worldnormal = normalize(vec4(%snormal, 0.0) * base.world_mtx);\n", flipNormal ? "-" : "");
|
||||
else
|
||||
WRITE(p, " mediump vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n");
|
||||
}
|
||||
|
||||
WRITE(p, " vec4 viewPos = vec4(vec4(worldpos, 1.0) * base.view_mtx, 1.0);\n");
|
||||
|
|
Loading…
Add table
Reference in a new issue