Commit 9f18f27e authored by Christopher Tenter's avatar Christopher Tenter

replace gluNurbs rendering with own implementation refs #2429

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@20774 383ad7c9-94d9-4d36-a494-682f7c89f535
parent aeb8b8cb
// preprocessor macros
// BSPLINE_DEGREE_U
// BSPLINE_DEGREE_V
// should be defined
#ifndef BSPLINE_DEGREE_U
#define BSPLINE_DEGREE_U 4
#endif
#ifndef BSPLINE_DEGREE_V
#define BSPLINE_DEGREE_V 4
#endif
// linear search
int bspline_find_span_ls(float u, samplerBuffer knots, int degree)
{
int i = 0;
int n = textureSize(knots);
float upperBound = texelFetch(knots, n - 1).x;
if (u >= upperBound)
return n - degree - 2;
float x = texelFetch(knots, i).x;
while (u >= x && i < n)
{
++i;
x = texelFetch(knots, i).x;
}
while (u < x && i >= 0)
{
--i;
x = texelFetch(knots, i).x;
}
return i;
}
// binary search
int bspline_find_span_bs(float u, samplerBuffer knots, int degree)
{
// binary search
// broken -> inf loop
int lo = degree;
int hi = textureSize(knots) - 1 - degree;
float upperBound = texelFetch(knots, hi).x;
if (u >= upperBound)
return hi - 1;
int mid = (lo + hi) / 2;
float knot_mid = texelFetch(knots, mid).x;
float knot_mid1 = texelFetch(knots, mid + 1).x;
while (u < knot_mid || u >= knot_mid1)
{
if (u < knot_mid)
hi = mid;
else
lo = mid;
mid = (lo + hi) / 2;
knot_mid = texelFetch(knots, mid).x;
knot_mid1 = texelFetch(knots, mid + 1).x;
}
return mid;
}
void bspline_derivs_U(out float N[BSPLINE_DEGREE_U+1], out float ND[BSPLINE_DEGREE_U+1], const int i, float u, samplerBuffer knots)
{
const int p = BSPLINE_DEGREE_U;
const int p1 = p+1;
vec2 lr[p1];
N[0] = 1;
for (int j = 1; j <= p; ++j)
{
lr[j].x = u - texelFetch(knots, i + 1 - j).x;
lr[j].y = texelFetch(knots, i + j).x - u;
float saved = 0;
for (int r = 0; r < j; ++r)
{
float left = lr[j-r].x;
float right = lr[r+1].y;
float tmp = N[r] / (left + right);
N[r] = saved + right * tmp;
saved = left * tmp;
}
N[j] = saved;
if (j == p - 1)
{
// N currently stores N(j, p-1), so compute derivatives now
// The NURBS Book p59 eq 2.7
// dN(i,p) / du = (p / (knot[i+p] - knot[i])) * N(i,p-1) - (p / (knot[i + p + 1] - knot[i + 1]) * N(i+1,p-1)
// evaluate this efficiently not only for i, but for all j = i-p, .., i
// left first N term is 0
float lterm = 0;
for (int r = 0; r < p; ++r)
{
// terms in in eq 2.7:
// index i: i - p + r
// lterm: p * N(i, p-1) / (knots[i+p] - knots[i]) (left term)
float kp1 = texelFetch(knots, i + 1 + r).x; // knots[i+p+1]
float kp2 = texelFetch(knots, i + 1 - p + r).x; // knots[i+1]
float rterm = float(p) * N[r] / (kp1 - kp2); // p * N(i+1, p-1)/ (kp1 - kp2)
ND[r] = lterm - rterm;
// right term is on the left for next N'(r+1, p)
lterm = rterm;
}
// right last N term is 0, only left term remains
ND[p] = lterm;
}
}
}
void bspline_derivs_V(out float N[BSPLINE_DEGREE_V+1], out float ND[BSPLINE_DEGREE_V+1], const int i, float u, samplerBuffer knots)
{
const int p = BSPLINE_DEGREE_V;
const int p1 = p+1;
vec2 lr[p1];
N[0] = 1;
for (int j = 1; j <= p; ++j)
{
lr[j].x = u - texelFetch(knots, i + 1 - j).x;
lr[j].y = texelFetch(knots, i + j).x - u;
float saved = 0;
for (int r = 0; r < j; ++r)
{
float left = lr[j-r].x;
float right = lr[r+1].y;
float tmp = N[r] / (left + right);
N[r] = saved + right * tmp;
saved = left * tmp;
}
N[j] = saved;
if (j == p - 1)
{
// N currently stores N(j, p-1), so compute derivatives now
saved = 0;
for (int r = 0; r < p; ++r)
{
float kp1 = texelFetch(knots, i + 1 + r).x;
float kp2 = texelFetch(knots, i + 1 - p + r).x;
float fac2 = float(p) * N[r] / (kp1 - kp2);
ND[r] = saved - fac2;
saved = fac2;
}
ND[p] = saved;
}
}
}
\ No newline at end of file
#version 400
#define SG_REQUEST_POSVS
layout(vertices = 3) out;
void main()
{
sg_MapIO(gl_InvocationID);
// lod based on distance to viewer
vec3 posVS = SG_INPUT_POSVS[gl_InvocationID].xyz;
float d2 = dot(posVS, posVS);
float d = sqrt(d2);
// sq, lin, const
vec3 atten = vec3(0.001, 0.08, 0.3);
float lod = 1.0 / (dot(atten, vec3(d2, d, 1.0)));
if (gl_InvocationID == 0)
{
float lod1 = lod, lod2 = lod;
gl_TessLevelInner[0] = lod1;
gl_TessLevelInner[1] = lod1;
gl_TessLevelOuter[0] = lod2;
gl_TessLevelOuter[1] = lod2;
gl_TessLevelOuter[2] = lod2;
gl_TessLevelOuter[3] = lod2;
}
}
\ No newline at end of file
#version 400
#define SG_REQUEST_TEXCOORD
#define SG_REQUEST_NORMALVS
layout(triangles, equal_spacing, ccw) in;
uniform samplerBuffer knotBufferU;
uniform samplerBuffer knotBufferV;
uniform sampler2D controlPointTex;
uniform vec4 uvRange;
#include "bspline_basis.glsl"
void main()
{
// sg_MapIOBilinear();
sg_MapIOBarycentric();
vec2 uv = SG_OUTPUT_TEXCOORD;
// map [0,1] to actual parameter range
uv.x = mix(uvRange.x, uvRange.y, uv.x);
uv.y = mix(uvRange.z, uvRange.w, uv.y);
// find span index (i) in u and v dir
int span_u = bspline_find_span_bs(uv.x, knotBufferU, BSPLINE_DEGREE_U);
int span_v = bspline_find_span_bs(uv.y, knotBufferV, BSPLINE_DEGREE_V);
float basisFuncsU[BSPLINE_DEGREE_U+1];
float basisFuncsV[BSPLINE_DEGREE_V+1];
float basisFuncsDU[BSPLINE_DEGREE_U+1];
float basisFuncsDV[BSPLINE_DEGREE_V+1];
bspline_derivs_U(basisFuncsU, basisFuncsDU, span_u, uv.x, knotBufferU);
bspline_derivs_V(basisFuncsV, basisFuncsDV, span_v, uv.y, knotBufferV);
// position
vec3 pos = vec3(0,0,0);
// tangents
vec3 dpdu = vec3(0,0,0); // derivative: d pos / du
vec3 dpdv = vec3(0,0,0); // derivative: d pos / dv
// linear combination
for (int x = 0; x <= BSPLINE_DEGREE_U; ++x)
{
for (int y = 0; y <= BSPLINE_DEGREE_V; ++y)
{
// load control point
ivec2 controlPtID = ivec2(span_u - BSPLINE_DEGREE_U + x, span_v - BSPLINE_DEGREE_V + y);
vec3 controlPt = texelFetch(controlPointTex, controlPtID, 0).xyz;
// combine
pos += controlPt * (basisFuncsU[x] * basisFuncsV[y]);
dpdu += controlPt * (basisFuncsDU[x] * basisFuncsV[y]);
dpdv += controlPt * (basisFuncsU[x] * basisFuncsDV[y]);
}
}
vec3 surfaceNormal = normalize(cross(dpdu, dpdv));
gl_Position = g_mWVP * vec4(pos, 1);
#ifdef SG_OUTPUT_POSOS
SG_OUTPUT_POSOS = vec4(pos, 1);
#endif
#ifdef SG_OUTPUT_POSVS
SG_OUTPUT_POSVS = g_mWV * vec4(pos, 1);
#endif
#ifdef SG_OUTPUT_POSCS
SG_OUTPUT_POSCS = gl_Position;
#endif
#ifdef SG_OUTPUT_NORMALOS
SG_OUTPUT_NORMALOS = surfaceNormal;
#endif
#ifdef SG_OUTPUT_NORMALVS
SG_OUTPUT_NORMALVS = g_mWVIT * surfaceNormal;
#endif
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment