|
|
@@ -46,12 +46,22 @@ class Fractal : public WorldEntity |
|
|
|
public: |
|
|
|
Fractal(ivec2 const &size) |
|
|
|
{ |
|
|
|
/* Ensure size has even X and Y values */ |
|
|
|
/* Ensure texture size is a multiple of 16 for better aligned |
|
|
|
* data access. Store the dimensions of a texel for our shader. */ |
|
|
|
m_size = size; |
|
|
|
m_size.x = (m_size.x + 1) & ~1; |
|
|
|
m_size.y = (m_size.y + 1) & ~1; |
|
|
|
m_size.x = (m_size.x + 15) & ~15; |
|
|
|
m_size.y = (m_size.y + 15) & ~15; |
|
|
|
m_texel_settings = vec4(vec2(1.0, 1.0) / (vec2)m_size, m_size); |
|
|
|
|
|
|
|
/* Window size decides the world aspect ratio. For instance, 640×480 |
|
|
|
* will be mapped to (-0.66,-0.5) - (0.66,0.5). */ |
|
|
|
m_window_size = Video::GetSize(); |
|
|
|
if (m_window_size.y < m_window_size.x) |
|
|
|
m_window2world = 0.5 / m_window_size.y; |
|
|
|
else |
|
|
|
m_window2world = 0.5 / m_window_size.x; |
|
|
|
m_texel2world = (vec2)m_window_size / (vec2)m_size * m_window2world; |
|
|
|
|
|
|
|
m_pixels = new u8vec4[m_size.x * m_size.y]; |
|
|
|
m_tmppixels = new u8vec4[m_size.x / 2 * m_size.y / 2]; |
|
|
|
m_frame = -1; |
|
|
@@ -62,24 +72,29 @@ public: |
|
|
|
m_dirty[i] = 2; |
|
|
|
} |
|
|
|
m_center = -0.75; |
|
|
|
m_radius = 1.5; |
|
|
|
m_texture_radius = 0.5 * (m_size.x < m_size.y ? m_size.x : m_size.y); |
|
|
|
m_window_radius = 0.5 * (m_window_size.x < m_window_size.y ? m_window_size.x : m_window_size.y); |
|
|
|
m_pixel_delta = vec4(vec2(1.0, 1.0) / (vec2)m_size, m_size); |
|
|
|
m_radius = 5.0; |
|
|
|
m_ready = false; |
|
|
|
|
|
|
|
m_palette = new u8vec4[(MAX_ITERATIONS + 1) * PALETTE_STEP]; |
|
|
|
for (int i = 0; i < (MAX_ITERATIONS + 1) * PALETTE_STEP; i++) |
|
|
|
{ |
|
|
|
float f = i / (double)PALETTE_STEP; |
|
|
|
double f = (double)i / PALETTE_STEP; |
|
|
|
|
|
|
|
double r = 0.5 * sin(f * 0.27 - 2.5) + 0.5; |
|
|
|
double g = 0.5 * sin(f * 0.13 + 1.1) + 0.5; |
|
|
|
double b = 0.5 * sin(f * 0.21 + 0.4) + 0.5; |
|
|
|
|
|
|
|
uint8_t red = r * 255.0f; |
|
|
|
uint8_t green = g * 255.0f; |
|
|
|
uint8_t blue = b * 255.0f; |
|
|
|
if (f < 7.0) |
|
|
|
{ |
|
|
|
f = f < 1.0 ? 0.0 : (f - 1.0) / 6.0; |
|
|
|
r *= f; |
|
|
|
g *= f; |
|
|
|
b *= f; |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t red = r * 255.99f; |
|
|
|
uint8_t green = g * 255.99f; |
|
|
|
uint8_t blue = b * 255.99f; |
|
|
|
m_palette[i] = u8vec4(blue, green, red, 0); |
|
|
|
} |
|
|
|
|
|
|
@@ -114,24 +129,25 @@ public: |
|
|
|
|
|
|
|
inline f64cmplx TexelToWorldOffset(ivec2 texel) |
|
|
|
{ |
|
|
|
f64cmplx tmp = f64cmplx(0.5 + texel.x - m_size.x / 2, |
|
|
|
0.5 + m_size.y / 2 - texel.y); |
|
|
|
return tmp * (m_radius / m_texture_radius); |
|
|
|
double dx = (0.5 + texel.x - m_size.x / 2) * m_texel2world.x; |
|
|
|
double dy = (0.5 + m_size.y / 2 - texel.y) * m_texel2world.y; |
|
|
|
return m_radius * f64cmplx(dx, dy); |
|
|
|
} |
|
|
|
|
|
|
|
inline f64cmplx ScreenToWorldOffset(ivec2 pixel) |
|
|
|
{ |
|
|
|
/* No 0.5 offset here, because we want to be able to position the |
|
|
|
* mouse at (0,0) exactly. */ |
|
|
|
f64cmplx tmp = f64cmplx(pixel.x - m_window_size.x / 2, |
|
|
|
m_window_size.y / 2 - pixel.y); |
|
|
|
return tmp * (m_radius / m_window_radius); |
|
|
|
double dx = pixel.x - m_window_size.x / 2; |
|
|
|
double dy = m_window_size.y / 2 - pixel.y; |
|
|
|
return m_radius * m_window2world * f64cmplx(dx, dy); |
|
|
|
} |
|
|
|
|
|
|
|
virtual void TickGame(float deltams) |
|
|
|
{ |
|
|
|
WorldEntity::TickGame(deltams); |
|
|
|
|
|
|
|
int prev_frame = m_frame; |
|
|
|
m_frame = (m_frame + 1) % 4; |
|
|
|
|
|
|
|
f64cmplx worldmouse = m_center + ScreenToWorldOffset(mousepos); |
|
|
@@ -160,23 +176,42 @@ public: |
|
|
|
worldmouse = m_center + ScreenToWorldOffset(mousepos); |
|
|
|
#endif |
|
|
|
|
|
|
|
/* Store the transformation properties to go from m_frame-1 |
|
|
|
/* Store the transformation properties to go from m_frame - 1 |
|
|
|
* to m_frame. */ |
|
|
|
m_deltashift[m_frame] = (oldcenter - m_center) / m_radius; |
|
|
|
m_deltascale[m_frame] = oldradius / m_radius; |
|
|
|
m_deltashift[prev_frame] = (m_center - oldcenter) / oldradius; |
|
|
|
m_deltashift[prev_frame].x /= m_size.x * m_texel2world.x; |
|
|
|
m_deltashift[prev_frame].y /= m_size.y * m_texel2world.y; |
|
|
|
m_deltascale[prev_frame] = m_radius / oldradius; |
|
|
|
m_dirty[0] = m_dirty[1] = m_dirty[2] = m_dirty[3] = 2; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
/* If settings didn't change, set transformation from previous |
|
|
|
* frame to identity. */ |
|
|
|
m_deltashift[m_frame] = 0.0; |
|
|
|
m_deltascale[m_frame] = 1.0; |
|
|
|
m_deltashift[prev_frame] = 0.0; |
|
|
|
m_deltascale[prev_frame] = 1.0; |
|
|
|
} |
|
|
|
|
|
|
|
if (buttons[1]) |
|
|
|
m_dirty[0] = m_dirty[1] = m_dirty[2] = m_dirty[3] = 2; |
|
|
|
|
|
|
|
/* Transformation from current frame to current frame is always |
|
|
|
* identity. */ |
|
|
|
m_zoom_settings[m_frame][0] = 0.0f; |
|
|
|
m_zoom_settings[m_frame][1] = 0.0f; |
|
|
|
m_zoom_settings[m_frame][2] = 1.0f; |
|
|
|
|
|
|
|
/* Compute transformation from other frames to current frame */ |
|
|
|
for (int i = 0; i < 3; i++) |
|
|
|
{ |
|
|
|
int prev_index = (m_frame + 4 - i) % 4; |
|
|
|
int cur_index = (m_frame + 3 - i) % 4; |
|
|
|
|
|
|
|
m_zoom_settings[cur_index][0] = m_zoom_settings[prev_index][0] * m_deltascale[cur_index] + m_deltashift[cur_index].x; |
|
|
|
m_zoom_settings[cur_index][1] = m_zoom_settings[prev_index][1] * m_deltascale[cur_index] + m_deltashift[cur_index].y; |
|
|
|
m_zoom_settings[cur_index][2] = m_zoom_settings[prev_index][2] * m_deltascale[cur_index]; |
|
|
|
} |
|
|
|
|
|
|
|
char buf[128]; |
|
|
|
sprintf(buf, "center: %+16.14f%+16.14fi", m_center.x, m_center.y); |
|
|
|
m_centertext->SetText(buf); |
|
|
@@ -291,43 +326,70 @@ public: |
|
|
|
|
|
|
|
"#version 120\n" |
|
|
|
"" |
|
|
|
"uniform vec4 in_PixelDelta;" |
|
|
|
"uniform vec4 in_TexelSize;" |
|
|
|
"uniform mat4 in_ZoomSettings;" |
|
|
|
"uniform sampler2D in_Texture;" |
|
|
|
"" |
|
|
|
"float mylen(vec2 p) {" |
|
|
|
//" return abs(p.x) + abs(p.y);" |
|
|
|
//" return p.x * p.x + p.y * p.y;" |
|
|
|
" return length(p);" |
|
|
|
"}" |
|
|
|
"" |
|
|
|
/* Get the coordinate of the nearest point in slice 0 in xy, |
|
|
|
* and the squared distance to that point in z. |
|
|
|
* p is in normalised [0,1] texture coordinates. |
|
|
|
* return value has the 0.25 Y scaling. */ |
|
|
|
"vec3 nearest0(vec2 p) {" |
|
|
|
" vec2 q = p + 0.5 * in_PixelDelta.xy;" |
|
|
|
" q -= mod(q, 2.0 * in_PixelDelta.xy);" |
|
|
|
" q += 0.5 * in_PixelDelta.xy;" |
|
|
|
" return vec3(q * vec2(1.0, 0.25)," |
|
|
|
" length(q - p));" |
|
|
|
" p -= vec2(0.5, 0.5);" |
|
|
|
" p *= in_ZoomSettings[0][2];" |
|
|
|
" p += vec2(in_ZoomSettings[0][0], -in_ZoomSettings[0][1]);" |
|
|
|
" p += vec2(0.5, 0.5);" |
|
|
|
" vec2 q = p + 0.5 * in_TexelSize.xy;" |
|
|
|
" q -= mod(q, 2.0 * in_TexelSize.xy);" |
|
|
|
" q += 0.5 * in_TexelSize.xy;" |
|
|
|
" float l = (abs(q.x - 0.5) < 0.5 && abs(q.y - 0.5) < 0.5)" |
|
|
|
" ? 1.0 / mylen(q - p) : 0.0;" |
|
|
|
" return vec3(q * vec2(1.0, 0.25), l);" |
|
|
|
"}" |
|
|
|
"" |
|
|
|
"vec3 nearest1(vec2 p) {" |
|
|
|
" vec2 q = p - 0.5 * in_PixelDelta.xy;" |
|
|
|
" q -= mod(q, 2.0 * in_PixelDelta.xy);" |
|
|
|
" q += 1.5 * in_PixelDelta.xy;" |
|
|
|
" return vec3(q * vec2(1.0, 0.25) + vec2(0.0, 0.25)," |
|
|
|
" length(q - p));" |
|
|
|
" p -= vec2(0.5, 0.5);" |
|
|
|
" p *= in_ZoomSettings[1][2];" |
|
|
|
" p += vec2(in_ZoomSettings[1][0], -in_ZoomSettings[1][1]);" |
|
|
|
" p += vec2(0.5, 0.5);" |
|
|
|
" vec2 q = p + -0.5 * in_TexelSize.xy;" |
|
|
|
" q -= mod(q, 2.0 * in_TexelSize.xy);" |
|
|
|
" q += 1.5 * in_TexelSize.xy;" |
|
|
|
" float l = (abs(q.x - 0.5) < 0.5 && abs(q.y - 0.5) < 0.5)" |
|
|
|
" ? 1.0 / mylen(q - p) : 0.0;" |
|
|
|
" return vec3(q * vec2(1.0, 0.25) + vec2(0.0, 0.25), l);" |
|
|
|
"}" |
|
|
|
"" |
|
|
|
"vec3 nearest2(vec2 p) {" |
|
|
|
" vec2 q = p + vec2(0.5, -0.5) * in_PixelDelta.xy;" |
|
|
|
" q -= mod(q, 2.0 * in_PixelDelta.xy);" |
|
|
|
" q += vec2(0.5, 1.5) * in_PixelDelta.xy;" |
|
|
|
" return vec3(q * vec2(1.0, 0.25) + vec2(0.0, 0.50)," |
|
|
|
" length(q - p));" |
|
|
|
" p -= vec2(0.5, 0.5);" |
|
|
|
" p *= in_ZoomSettings[2][2];" |
|
|
|
" p += vec2(in_ZoomSettings[2][0], -in_ZoomSettings[2][1]);" |
|
|
|
" p += vec2(0.5, 0.5);" |
|
|
|
" vec2 q = p + vec2(0.5, -0.5) * in_TexelSize.xy;" |
|
|
|
" q -= mod(q, 2.0 * in_TexelSize.xy);" |
|
|
|
" q += vec2(0.5, 1.5) * in_TexelSize.xy;" |
|
|
|
" float l = (abs(q.x - 0.5) < 0.5 && abs(q.y - 0.5) < 0.5)" |
|
|
|
" ? 1.0 / mylen(q - p) : 0.0;" |
|
|
|
" return vec3(q * vec2(1.0, 0.25) + vec2(0.0, 0.50), l);" |
|
|
|
"}" |
|
|
|
"" |
|
|
|
"vec3 nearest3(vec2 p) {" |
|
|
|
" vec2 q = p + vec2(-0.5, 0.5) * in_PixelDelta.xy;" |
|
|
|
" q -= mod(q, 2.0 * in_PixelDelta.xy);" |
|
|
|
" q += vec2(1.5, 0.5) * in_PixelDelta.xy;" |
|
|
|
" return vec3(q * vec2(1.0, 0.25) + vec2(0.0, 0.75)," |
|
|
|
" length(q - p));" |
|
|
|
" p -= vec2(0.5, 0.5);" |
|
|
|
" p *= in_ZoomSettings[3][2];" |
|
|
|
" p += vec2(in_ZoomSettings[3][0], -in_ZoomSettings[3][1]);" |
|
|
|
" p += vec2(0.5, 0.5);" |
|
|
|
" vec2 q = p + vec2(-0.5, 0.5) * in_TexelSize.xy;" |
|
|
|
" q -= mod(q, 2.0 * in_TexelSize.xy);" |
|
|
|
" q += vec2(1.5, 0.5) * in_TexelSize.xy;" |
|
|
|
" float l = (abs(q.x - 0.5) < 0.5 && abs(q.y - 0.5) < 0.5)" |
|
|
|
" ? 1.0 / mylen(q - p) : 0.0;" |
|
|
|
" return vec3(q * vec2(1.0, 0.25) + vec2(0.0, 0.75), l);" |
|
|
|
"}" |
|
|
|
"" |
|
|
|
"void main(void) {" |
|
|
@@ -335,13 +397,22 @@ public: |
|
|
|
/* Slightly shift our pixel so that it does not lie at |
|
|
|
* an exact texel boundary. This would lead to visual |
|
|
|
* artifacts. */ |
|
|
|
" coord -= 0.1 * in_PixelDelta.xy;" |
|
|
|
" coord -= 0.1 * in_TexelSize.xy;" |
|
|
|
/* Get a pixel from each slice */ |
|
|
|
" vec4 p0 = texture2D(in_Texture, nearest0(coord).xy);" |
|
|
|
" vec4 p1 = texture2D(in_Texture, nearest1(coord).xy);" |
|
|
|
" vec4 p2 = texture2D(in_Texture, nearest2(coord).xy);" |
|
|
|
" vec4 p3 = texture2D(in_Texture, nearest3(coord).xy);" |
|
|
|
" gl_FragColor = 0.25 * (p0 + p1 + p2 + p3);" |
|
|
|
" vec3 k0 = nearest0(coord);" |
|
|
|
" vec3 k1 = nearest1(coord);" |
|
|
|
" vec3 k2 = nearest2(coord);" |
|
|
|
" vec3 k3 = nearest3(coord);" |
|
|
|
" vec4 p0 = texture2D(in_Texture, k0.xy);" |
|
|
|
" vec4 p1 = texture2D(in_Texture, k1.xy);" |
|
|
|
" vec4 p2 = texture2D(in_Texture, k2.xy);" |
|
|
|
" vec4 p3 = texture2D(in_Texture, k3.xy);" |
|
|
|
//"if (k0.z >= k1.z && k0.z >= k2.z && k0.z >= k3.z) gl_FragColor = p0;" |
|
|
|
//"if (k1.z >= k0.z && k1.z >= k2.z && k1.z >= k3.z) gl_FragColor = p1;" |
|
|
|
//"if (k2.z >= k0.z && k2.z >= k1.z && k2.z >= k3.z) gl_FragColor = p2;" |
|
|
|
//"if (k3.z >= k0.z && k3.z >= k1.z && k3.z >= k2.z) gl_FragColor = p3;" |
|
|
|
" gl_FragColor = 1.0 / (k0.z + k1.z + k2.z + k3.z)" |
|
|
|
" * (k0.z * p0 + k1.z * p1 + k2.z * p2 + k3.z * p3);" |
|
|
|
"}" |
|
|
|
#else |
|
|
|
"void main(float4 in_Position : POSITION," |
|
|
@@ -353,56 +424,57 @@ public: |
|
|
|
" out_Position = in_Position;" |
|
|
|
"}", |
|
|
|
|
|
|
|
"float3 nearest0(float2 p, float4 in_PixelDelta) {" |
|
|
|
" float2 q = p + 0.5 * in_PixelDelta.xy;" |
|
|
|
" q -= fmod(q, 2.0 * in_PixelDelta.xy);" |
|
|
|
" q += 0.5 * in_PixelDelta.xy;" |
|
|
|
"float3 nearest0(float2 p, float4 in_TexelSize) {" |
|
|
|
" float2 q = p + 0.5 * in_TexelSize.xy;" |
|
|
|
" q -= fmod(q, 2.0 * in_TexelSize.xy);" |
|
|
|
" q += 0.5 * in_TexelSize.xy;" |
|
|
|
" return float3(q * float2(1.0, 0.25)," |
|
|
|
" length(q - p));" |
|
|
|
"}" |
|
|
|
"" |
|
|
|
"float3 nearest1(float2 p, float4 in_PixelDelta) {" |
|
|
|
" float2 q = p - 0.5 * in_PixelDelta.xy;" |
|
|
|
" q -= fmod(q, 2.0 * in_PixelDelta.xy);" |
|
|
|
" q += 1.5 * in_PixelDelta.xy;" |
|
|
|
"float3 nearest1(float2 p, float4 in_TexelSize) {" |
|
|
|
" float2 q = p - 0.5 * in_TexelSize.xy;" |
|
|
|
" q -= fmod(q, 2.0 * in_TexelSize.xy);" |
|
|
|
" q += 1.5 * in_TexelSize.xy;" |
|
|
|
" return float3(q * float2(1.0, 0.25) + float2(0.0, 0.25)," |
|
|
|
" length(q - p));" |
|
|
|
"}" |
|
|
|
"" |
|
|
|
"float3 nearest2(float2 p, float4 in_PixelDelta) {" |
|
|
|
" float2 q = p + float2(0.5, -0.5) * in_PixelDelta.xy;" |
|
|
|
" q -= fmod(q, 2.0 * in_PixelDelta.xy);" |
|
|
|
" q += float2(0.5, 1.5) * in_PixelDelta.xy;" |
|
|
|
"float3 nearest2(float2 p, float4 in_TexelSize) {" |
|
|
|
" float2 q = p + float2(0.5, -0.5) * in_TexelSize.xy;" |
|
|
|
" q -= fmod(q, 2.0 * in_TexelSize.xy);" |
|
|
|
" q += float2(0.5, 1.5) * in_TexelSize.xy;" |
|
|
|
" return float3(q * float2(1.0, 0.25) + float2(0.0, 0.50)," |
|
|
|
" length(q - p));" |
|
|
|
"}" |
|
|
|
"" |
|
|
|
"float3 nearest3(float2 p, float4 in_PixelDelta) {" |
|
|
|
" float2 q = p + float2(-0.5, 0.5) * in_PixelDelta.xy;" |
|
|
|
" q -= fmod(q, 2.0 * in_PixelDelta.xy);" |
|
|
|
" q += float2(1.5, 0.5) * in_PixelDelta.xy;" |
|
|
|
"float3 nearest3(float2 p, float4 in_TexelSize) {" |
|
|
|
" float2 q = p + float2(-0.5, 0.5) * in_TexelSize.xy;" |
|
|
|
" q -= fmod(q, 2.0 * in_TexelSize.xy);" |
|
|
|
" q += float2(1.5, 0.5) * in_TexelSize.xy;" |
|
|
|
" return float3(q * float2(1.0, 0.25) + float2(0.0, 0.75)," |
|
|
|
" length(q - p));" |
|
|
|
"}" |
|
|
|
"" |
|
|
|
"void main(float2 in_TexCoord : TEXCOORD0," |
|
|
|
" uniform float4 in_PixelDelta," |
|
|
|
" uniform float4 in_TexelSize," |
|
|
|
" uniform sampler2D in_Texture," |
|
|
|
" out float4 out_FragColor : COLOR)" |
|
|
|
"{" |
|
|
|
" float2 coord = in_TexCoord.xy;" |
|
|
|
" coord -= 0.1 * in_PixelDelta.xy;" |
|
|
|
" float4 p0 = tex2D(in_Texture, nearest0(coord, in_PixelDelta).xy);" |
|
|
|
" float4 p1 = tex2D(in_Texture, nearest1(coord, in_PixelDelta).xy);" |
|
|
|
" float4 p2 = tex2D(in_Texture, nearest2(coord, in_PixelDelta).xy);" |
|
|
|
" float4 p3 = tex2D(in_Texture, nearest3(coord, in_PixelDelta).xy);" |
|
|
|
" coord -= 0.1 * in_TexelSize.xy;" |
|
|
|
" float4 p0 = tex2D(in_Texture, nearest0(coord, in_TexelSize).xy);" |
|
|
|
" float4 p1 = tex2D(in_Texture, nearest1(coord, in_TexelSize).xy);" |
|
|
|
" float4 p2 = tex2D(in_Texture, nearest2(coord, in_TexelSize).xy);" |
|
|
|
" float4 p3 = tex2D(in_Texture, nearest3(coord, in_TexelSize).xy);" |
|
|
|
" out_FragColor = 0.25 * (p0 + p1 + p2 + p3);" |
|
|
|
"}" |
|
|
|
#endif |
|
|
|
); |
|
|
|
m_vertexattrib = m_shader->GetAttribLocation("in_Vertex"); |
|
|
|
m_texattrib = m_shader->GetAttribLocation("in_TexCoord"); |
|
|
|
m_pixeluni = m_shader->GetUniformLocation("in_PixelDelta"); |
|
|
|
m_texeluni = m_shader->GetUniformLocation("in_TexelSize"); |
|
|
|
m_zoomuni = m_shader->GetUniformLocation("in_ZoomSettings"); |
|
|
|
m_ready = true; |
|
|
|
|
|
|
|
#if !defined __CELLOS_LV2__ && !defined __ANDROID__ |
|
|
@@ -445,7 +517,8 @@ public: |
|
|
|
} |
|
|
|
|
|
|
|
m_shader->Bind(); |
|
|
|
m_shader->SetUniform(m_pixeluni, m_pixel_delta); |
|
|
|
m_shader->SetUniform(m_texeluni, m_texel_settings); |
|
|
|
m_shader->SetUniform(m_zoomuni, m_zoom_settings); |
|
|
|
#if !defined __CELLOS_LV2__ && !defined __ANDROID__ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo); |
|
|
|
glEnableVertexAttribArray(m_vertexattrib); |
|
|
@@ -486,6 +559,8 @@ private: |
|
|
|
static int const PALETTE_STEP = 32; |
|
|
|
|
|
|
|
ivec2 m_size, m_window_size; |
|
|
|
double m_window2world; |
|
|
|
f64vec2 m_texel2world; |
|
|
|
u8vec4 *m_pixels, *m_tmppixels, *m_palette; |
|
|
|
Shader *m_shader; |
|
|
|
GLuint m_texid; |
|
|
@@ -493,13 +568,14 @@ private: |
|
|
|
GLuint m_vbo, m_tbo; |
|
|
|
GLuint m_tco; |
|
|
|
#endif |
|
|
|
int m_vertexattrib, m_texattrib, m_pixeluni; |
|
|
|
int m_vertexattrib, m_texattrib, m_texeluni, m_zoomuni; |
|
|
|
int m_frame, m_dirty[4]; |
|
|
|
bool m_ready; |
|
|
|
|
|
|
|
f64cmplx m_center; |
|
|
|
double m_radius, m_texture_radius, m_window_radius; |
|
|
|
vec4 m_pixel_delta; |
|
|
|
double m_radius; |
|
|
|
vec4 m_texel_settings; |
|
|
|
mat4 m_zoom_settings; |
|
|
|
f64cmplx m_deltashift[4]; |
|
|
|
double m_deltascale[4]; |
|
|
|
|
|
|
|