terrain_kernels.cl
// |
// File: terrain_kernels.cl |
// |
// Abstract: This example shows how OpenCL can be used to create a procedural field of |
// grass on a generated terrain model which is then rendered with OpenGL. |
// Because OpenGL buffers are shared with OpenCL, the data can remain on the |
// graphics card, thus eliminating the API overhead of creating and submitting |
// the vertices from the host. |
// |
// All geometry is generated on the compute device, and outputted into |
// a shared OpenGL buffer. The terrain gets generated only within the |
// visible arc covering the camera's view frustum to avoid the need for |
// culling. A page of grass is computed on the surface of the terrain as |
// bezier patches, and flow noise is applied to the angle of the blades |
// to simulate wind. Multiple instances of grass are rendered at jittered |
// offsets to add more grass coverage without having to compute new pages. |
// Finally, a physically based sky shader (via OpenGL) is applied to |
// the background to provide an environment for the grass. |
// |
// Version: <1.0> |
// |
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") |
// in consideration of your agreement to the following terms, and your use, |
// installation, modification or redistribution of this Apple software |
// constitutes acceptance of these terms. If you do not agree with these |
// terms, please do not use, install, modify or redistribute this Apple |
// software. |
// |
// In consideration of your agreement to abide by the following terms, and |
// subject to these terms, Apple grants you a personal, non - exclusive |
// license, under Apple's copyrights in this original Apple software ( the |
// "Apple Software" ), to use, reproduce, modify and redistribute the Apple |
// Software, with or without modifications, in source and / or binary forms; |
// provided that if you redistribute the Apple Software in its entirety and |
// without modifications, you must retain this notice and the following text |
// and disclaimers in all such redistributions of the Apple Software. Neither |
// the name, trademarks, service marks or logos of Apple Inc. may be used to |
// endorse or promote products derived from the Apple Software without specific |
// prior written permission from Apple. Except as expressly stated in this |
// notice, no other rights or licenses, express or implied, are granted by |
// Apple herein, including but not limited to any patent rights that may be |
// infringed by your derivative works or by other works in which the Apple |
// Software may be incorporated. |
// |
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
// WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
// WARRANTIES OF NON - INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A |
// PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION |
// ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
// |
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
// CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
// INTERRUPTION ) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION |
// AND / OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER |
// UNDER THEORY OF CONTRACT, TORT ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR |
// OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
// |
// Copyright ( C ) 2008 Apple Inc. All Rights Reserved. |
// |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
#ifndef M_PI |
#define M_PI 3.14159265358979323846264338327950288 /* pi */ |
#endif |
#define DEG_TO_RAD ((float)(M_PI / 180.0)) |
#define RADIANS(x) (radians((x))) |
#define ONE_F1 (1.0f) |
#define ZERO_F1 (0.0f) |
static const float4 ZERO_F4 = (float4){ 0.0f, 0.0f, 0.0f, 0.0f }; |
static const float4 ONE_F4 = (float4){ 1.0f, 1.0f, 1.0f, 1.0f }; |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
__constant int P_MASK = 255; |
__constant int P_SIZE = 256; |
__constant int P[512] = {151,160,137,91,90,15, |
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, |
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, |
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, |
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, |
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, |
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, |
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, |
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, |
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, |
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, |
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, |
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, |
151,160,137,91,90,15, |
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, |
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, |
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, |
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, |
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, |
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, |
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, |
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, |
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, |
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, |
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, |
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, |
}; |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
__constant int G_MASK = 15; |
__constant int G_SIZE = 16; |
__constant int G_VECSIZE = 4; |
__constant float G[16*4] = { |
+ONE_F1, +ONE_F1, +ZERO_F1, +ZERO_F1, |
-ONE_F1, +ONE_F1, +ZERO_F1, +ZERO_F1, |
+ONE_F1, -ONE_F1, +ZERO_F1, +ZERO_F1, |
-ONE_F1, -ONE_F1, +ZERO_F1, +ZERO_F1, |
+ONE_F1, +ZERO_F1, +ONE_F1, +ZERO_F1, |
-ONE_F1, +ZERO_F1, +ONE_F1, +ZERO_F1, |
+ONE_F1, +ZERO_F1, -ONE_F1, +ZERO_F1, |
-ONE_F1, +ZERO_F1, -ONE_F1, +ZERO_F1, |
+ZERO_F1, +ONE_F1, +ONE_F1, +ZERO_F1, |
+ZERO_F1, -ONE_F1, +ONE_F1, +ZERO_F1, |
+ZERO_F1, +ONE_F1, -ONE_F1, +ZERO_F1, |
+ZERO_F1, -ONE_F1, -ONE_F1, +ZERO_F1, |
+ONE_F1, +ONE_F1, +ZERO_F1, +ZERO_F1, |
-ONE_F1, +ONE_F1, +ZERO_F1, +ZERO_F1, |
+ZERO_F1, -ONE_F1, +ONE_F1, +ZERO_F1, |
+ZERO_F1, -ONE_F1, -ONE_F1, +ZERO_F1 |
}; |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
int mod(int x, int a) |
{ |
int n = (x / a); |
int v = v - n * a; |
if ( v < 0 ) |
v += a; |
return v; |
} |
float smooth(float t) |
{ |
return t*t*t*(t*(t*6.0f-15.0f)+10.0f); |
} |
float4 normalized(float4 v) |
{ |
float d = sqrt(v.x * v.x + v.y * v.y + v.z * v.z); |
d = d > 0.0f ? d : 1.0f; |
float4 result = (float4){ v.x, v.y, v.z, 0.0f }; |
result /= d; |
result.w = 1.0f; |
return result; |
} |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
float mix1d(float a, float b, float t) |
{ |
float ba = b - a; |
float tba = t * ba; |
float atba = a + tba; |
return atba; |
} |
float2 mix2d(float2 a, float2 b, float t) |
{ |
float2 ba = b - a; |
float2 tba = t * ba; |
float2 atba = a + tba; |
return atba; |
} |
float4 mix3d(float4 a, float4 b, float t) |
{ |
float4 ba = b - a; |
float4 tba = t * ba; |
float4 atba = a + tba; |
return atba; |
} |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
int lattice1d(int i) |
{ |
return P[i]; |
} |
int lattice2d(int2 i) |
{ |
return P[i.x + P[i.y]]; |
} |
int lattice3d(int4 i) |
{ |
return P[i.x + P[i.y + P[i.z]]]; |
} |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
float gradient1d(int i, float v) |
{ |
int index = (lattice1d(i) & G_MASK) * G_VECSIZE; |
float g = G[index + 0]; |
return (v * g); |
} |
float gradient2d(int2 i, float2 v) |
{ |
int index = (lattice2d(i) & G_MASK) * G_VECSIZE; |
float2 g = (float2){ G[index + 0], G[index + 1] }; |
return dot(v, g); |
} |
float gradient3d(int4 i, float4 v) |
{ |
int index = (lattice3d(i) & G_MASK) * G_VECSIZE; |
float4 g = (float4){ G[index + 0], G[index + 1], G[index + 2], 1.0f }; |
return dot(v, g); |
} |
float2 rotated_gradient2d(int2 i, float2 v, float2 r) |
{ |
int index = (lattice2d(i) & G_MASK) * G_VECSIZE; |
float2 g = (float2){ G[index + 0], G[index + 1] }; |
g.x = r.x * g.x - r.y * g.y; |
g.y = r.y * g.x + r.x * g.y; |
return g; |
} |
float dot_rotated_gradient2d(int2 i, float2 v, float2 r) |
{ |
int index = (lattice2d(i) & G_MASK) * G_VECSIZE; |
float2 g = (float2){ G[index + 0], G[index + 1] }; |
g.x = r.x * g.x - r.y * g.y; |
g.y = r.y * g.x + r.x * g.y; |
return dot(v, g); |
} |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
// Unsigned cell noise 1d (+0.0f -> +1.0f) |
float CellNoise1dfu(float position) |
{ |
float p = position; |
float pf = floor(p); |
int ip = (int)pf; |
float fp = p - pf; |
ip &= P_MASK; |
return (lattice1d(ip) * (1.0f / (P_SIZE - 1))); |
} |
// Signed cell noise 1d (-1.0 -> +1.0f) |
float CellNoise1dfs(float position) |
{ |
return 2.0f * CellNoise1dfu(position) - 1.0f; |
} |
// Unsigned cell noise 2d (+0.0f -> +1.0f) |
float CellNoise2dfu(float2 position) |
{ |
float2 p = position; |
float2 pf = floor(p); |
int2 ip = (int2){ (int)pf.x, (int)pf.y }; |
float2 fp = p - pf; |
ip &= P_MASK; |
return (lattice2d(ip) * (1.0f / (P_SIZE - 1))); |
} |
// Signed cell noise 2d (-1.0 -> +1.0f) |
float CellNoise2dfs(float2 position) |
{ |
return 2.0f * CellNoise2dfu(position) - 1.0f; |
} |
// Unsigned cell noise 3d (+0.0f -> +1.0f) |
float CellNoise3dfu(float4 position) |
{ |
float4 p = position; |
float4 pf = floor(p); |
int4 ip = (int4){(int)pf.x, (int)pf.y, (int)pf.z, 0 }; |
float4 fp = p - pf; |
ip &= P_MASK; |
return (lattice3d(ip) * (1.0f / (P_SIZE - 1))); |
} |
// Signed cell noise 2d (-1.0 -> +1.0f) |
float CellNoise3dfs(float4 position) |
{ |
return 2.0f * CellNoise3dfu(position) - 1.0f; |
} |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
// Signed gradient noise 1d (-1.0 -> +1.0f) |
float GradientNoise1dfs(float position) |
{ |
float p = position; |
float pf = floor(p); |
int ip = (int)pf; |
float fp = p - pf; |
ip &= P_MASK; |
float n0 = gradient1d(ip + 0, fp - 0.0f); |
float n1 = gradient1d(ip + 1, fp - 1.0f); |
float n = mix1d(n0, n1, smooth(fp)); |
return n * (1.0f / 0.7f); |
} |
// Unsigned Gradient Noise 1d |
float GradientNoise1dfu(float position) |
{ |
return (0.5f - 0.5f * GradientNoise1dfs(position)); |
} |
// Signed gradient noise 2d (-1.0 -> +1.0f) |
float GradientNoise2dfs(float2 position) |
{ |
float2 p = position; |
float2 pf = floor(p); |
int2 ip = (int2){ (int)pf.x, (int)pf.y }; |
float2 fp = p - pf; |
ip &= P_MASK; |
const int2 I00 = (int2){ 0, 0 }; |
const int2 I01 = (int2){ 0, 1 }; |
const int2 I10 = (int2){ 1, 0 }; |
const int2 I11 = (int2){ 1, 1 }; |
const float2 F00 = (float2){ 0.0f, 0.0f }; |
const float2 F01 = (float2){ 0.0f, 1.0f }; |
const float2 F10 = (float2){ 1.0f, 0.0f }; |
const float2 F11 = (float2){ 1.0f, 1.0f }; |
float n00 = gradient2d(ip + I00, fp - F00); |
float n10 = gradient2d(ip + I10, fp - F10); |
float n01 = gradient2d(ip + I01, fp - F01); |
float n11 = gradient2d(ip + I11, fp - F11); |
const float2 n0001 = (float2){ n00, n01 }; |
const float2 n1011 = (float2){ n10, n11 }; |
float2 n2 = mix2d(n0001, n1011, smooth(fp.x)); |
float n = mix1d(n2.x, n2.y, smooth(fp.y)); |
return n * (1.0f / 0.7f); |
} |
// Unsigned Gradient Noise 2d |
float GradientNoise2dfu(float2 position) |
{ |
return (0.5f - 0.5f * GradientNoise2dfs(position)); |
} |
// Signed gradient noise 3d (-1.0 -> +1.0f) |
float GradientNoise3dfs(float4 position) |
{ |
float4 p = position; |
float4 pf = floor(p); |
int4 ip = (int4){(int)pf.x, (int)pf.y, (int)pf.z, 0 }; |
float4 fp = p - pf; |
ip &= P_MASK; |
int4 I000 = (int4){0, 0, 0, 0}; |
int4 I001 = (int4){0, 0, 1, 0}; |
int4 I010 = (int4){0, 1, 0, 0}; |
int4 I011 = (int4){0, 1, 1, 0}; |
int4 I100 = (int4){1, 0, 0, 0}; |
int4 I101 = (int4){1, 0, 1, 0}; |
int4 I110 = (int4){1, 1, 0, 0}; |
int4 I111 = (int4){1, 1, 1, 0}; |
float4 F000 = (float4){ 0.0f, 0.0f, 0.0f, 0.0f }; |
float4 F001 = (float4){ 0.0f, 0.0f, 1.0f, 0.0f }; |
float4 F010 = (float4){ 0.0f, 1.0f, 0.0f, 0.0f }; |
float4 F011 = (float4){ 0.0f, 1.0f, 1.0f, 0.0f }; |
float4 F100 = (float4){ 1.0f, 0.0f, 0.0f, 0.0f }; |
float4 F101 = (float4){ 1.0f, 0.0f, 1.0f, 0.0f }; |
float4 F110 = (float4){ 1.0f, 1.0f, 0.0f, 0.0f }; |
float4 F111 = (float4){ 1.0f, 1.0f, 1.0f, 0.0f }; |
float n000 = gradient3d(ip + I000, fp - F000); |
float n001 = gradient3d(ip + I001, fp - F001); |
float n010 = gradient3d(ip + I010, fp - F010); |
float n011 = gradient3d(ip + I011, fp - F011); |
float n100 = gradient3d(ip + I100, fp - F100); |
float n101 = gradient3d(ip + I101, fp - F101); |
float n110 = gradient3d(ip + I110, fp - F110); |
float n111 = gradient3d(ip + I111, fp - F111); |
float4 n40 = (float4){ n000, n001, n010, n011 }; |
float4 n41 = (float4){ n100, n101, n110, n111 }; |
float4 n4 = mix3d(n40, n41, smooth(fp.x)); |
float2 n2 = mix2d(n4.xy, n4.zw, smooth(fp.y)); |
float n = mix1d(n2.x, n2.y, smooth(fp.z)); |
return n * (1.0f / 0.7f); |
} |
// Unsigned Gradient Noise 3d |
float GradientNoise3dfu(float4 position) |
{ |
return (0.5f - 0.5f * GradientNoise3dfs(position)); |
} |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
float RotatedGradientNoise2dfs(float2 position, float angle) |
{ |
float2 p = position; |
float2 pf = floor(p); |
int2 ip = (int2){ (int)pf.x, (int)pf.y }; |
float2 fp = p - pf; |
ip &= P_MASK; |
float r = radians(angle); |
float2 rg = (float2){ native_sin(r), native_cos(r) }; |
const int2 I00 = (int2){ 0, 0 }; |
const int2 I01 = (int2){ 0, 1 }; |
const int2 I10 = (int2){ 1, 0 }; |
const int2 I11 = (int2){ 1, 1 }; |
const float2 F00 = (float2){ 0.0f, 0.0f }; |
const float2 F01 = (float2){ 0.0f, 1.0f }; |
const float2 F10 = (float2){ 1.0f, 0.0f }; |
const float2 F11 = (float2){ 1.0f, 1.0f }; |
float n00 = dot_rotated_gradient2d(ip + I00, fp - F00, rg); |
float n10 = dot_rotated_gradient2d(ip + I10, fp - F10, rg); |
float n01 = dot_rotated_gradient2d(ip + I01, fp - F01, rg); |
float n11 = dot_rotated_gradient2d(ip + I11, fp - F11, rg); |
const float2 n0001 = (float2){ n00, n01 }; |
const float2 n1011 = (float2){ n10, n11 }; |
float2 n2 = mix2d(n0001, n1011, smooth(fp.x)); |
float n = mix1d(n2.x, n2.y, smooth(fp.y)); |
return n * (1.0f / 0.7f); |
} |
float4 |
RotatedSimplexNoise2dfs( |
float2 position, float angle ) |
{ |
float2 p = position; |
float r = radians(angle); |
float2 rg = (float2){ native_sin(r), native_cos(r) }; |
const float F2 = 0.366025403f; // 0.5*(sqrt(3.0)-1.0) |
const float G2 = 0.211324865f; // (3.0-Math.sqrt(3.0))/6.0 |
const float G22 = 2.0f * G2; |
const float2 FF = (float2){ F2, F2 }; |
const float2 GG = (float2){ G2, G2 }; |
const float2 GG2 = (float2){ G22, G22 }; |
const float2 F00 = (float2){ 0.0f, 0.0f }; |
const float2 F01 = (float2){ 0.0f, 1.0f }; |
const float2 F10 = (float2){ 1.0f, 0.0f }; |
const float2 F11 = (float2){ 1.0f, 1.0f }; |
const int2 I00 = (int2){ 0, 0 }; |
const int2 I01 = (int2){ 0, 1 }; |
const int2 I10 = (int2){ 1, 0 }; |
const int2 I11 = (int2){ 1, 1 }; |
float s = ( p.x + p.y ) * F2; |
float2 ps = (float2){ p.x + s, p.y + s }; |
float2 pf = floor(ps); |
int2 ip = (int2){ (int)pf.x, (int)pf.y }; |
ip &= (int2){ P_MASK, P_MASK }; |
float t = ( pf.x + pf.y ) * G2; |
float2 tt = (float2){ t, t }; |
float2 tf = pf - tt; |
float2 fp = p - tf; |
float2 p0 = fp; |
int2 i1 = (p0.x > p0.y) ? (I10) : (I01); |
float2 f1 = (p0.x > p0.y) ? (F10) : (F01); |
float2 p1 = p0 - f1 + GG; |
float2 p2 = p0 - F11 + GG2; |
float t0 = 0.5f - p0.x * p0.x - p0.y * p0.y; |
float t1 = 0.5f - p1.x * p1.x - p1.y * p1.y; |
float t2 = 0.5f - p2.x * p2.x - p2.y * p2.y; |
float2 g0 = F00; |
float2 g1 = F00; |
float2 g2 = F00; |
float n0 = 0.0f; |
float n1 = 0.0f; |
float n2 = 0.0f; |
float t20 = 0.0f; |
float t40 = 0.0f; |
float t21 = 0.0f; |
float t41 = 0.0f; |
float t22 = 0.0f; |
float t42 = 0.0f; |
if(t0 >= 0.0f) |
{ |
g0 = rotated_gradient2d(ip + I00, p0, rg); |
t20 = t0 * t0; |
t40 = t20 * t20; |
n0 = t40 * dot(p0, g0); |
} |
if(t1 >= 0.0f) |
{ |
g1 = rotated_gradient2d(ip + i1, p1, rg); |
t21 = t1 * t1; |
t41 = t21 * t21; |
n1 = t41 * dot(p1, g1); |
} |
if(t2 >= 0.0f) |
{ |
g2 = rotated_gradient2d(ip + I11, p2, rg); |
t22 = t2 * t2; |
t42 = t22 * t22; |
n2 = t42 * dot(p2, g2); |
} |
float noise = 40.0f * ( n0 + n1 + n2 ); |
float2 dn = p0 * t20 * t0 * dot(p0, g0); |
dn += p1 * t21 * t1 * dot(p1, g1); |
dn += p2 * t22 * t2 * dot(p2, g2); |
dn *= -8.0f; |
dn += t40 * g0 + t41 * g1 + t42 * g2; |
dn *= 40.0f; |
return (float4){ noise, dn.x, dn.y, 1.0f }; |
} |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
float4 |
ComputeRadialGridPosition( |
float2 uv, |
float2 vt, |
float2 ve, |
float4 camera_position, |
float4 camera_rotation, |
float4 camera_view, |
float4 camera_left, |
float camera_fov) |
{ |
float4 normal = (float4){ 0.0f, 1.0f, 0.0f, 1.0f }; |
float ndl = fmax(0.1f, (dot(normal, camera_view))); |
float extend = 20.0f / ndl; |
float ninety = RADIANS(90.0f); |
float cr = RADIANS(camera_rotation.x) + RADIANS(camera_fov - extend * 0.5f); |
float angle = RADIANS(camera_fov + extend) * uv.y; |
angle = (angle >= RADIANS(180.0f)) ? (angle - RADIANS(180.0f)) : angle; |
cr += (angle >= RADIANS(180.0f)) ? RADIANS(-camera_rotation.x) : 0.0f; |
float s = (cr > 0.0f) ? (1.0f) : (-1.0f); |
float a0 = 0.1f; |
float a1 = 0.05f / ve.x * ve.y; |
float x2 = vt.x * vt.x; |
float fr = a0 + a1 * x2; |
float fx = fr * native_cos(cr + angle); |
float fy = fr * native_sin(cr + angle); |
float4 view = (float4){ 0.0f, 0.0f, fy, 1.0f }; |
float4 left = (float4){ -fx, 0.0f, 0.0f, 1.0f }; |
float4 position = camera_position - camera_view * extend * 0.25f + view + left; |
position.y = 0.0f; |
position.w = 1.0f; |
return position; |
} |
float2 |
GetGridCoordinates(int index, int2 size) |
{ |
float2 coord; |
coord.x = index % size.x; |
index /= size.x; |
coord.y = index % size.y; |
return coord; |
} |
__kernel void |
ComputeTerrainKernel( |
int2 grid_resolution, |
float4 camera_position, |
float4 camera_rotation, |
float4 camera_view, |
float4 camera_left, |
float camera_fov, |
uint vertex_count, |
__global float4 *vertices, |
__global float4 *normals, |
__global float2 *texcoords) |
{ |
int tx = get_global_id(0); |
int ty = get_global_id(1); |
int sx = get_global_size(0); |
int sy = get_global_size(1); |
int index = ty * sx + tx; |
if(index > vertex_count) |
return; |
float frequency = 0.0025f; |
float amplitude = 70.00f; |
float phase = 1.0f; |
float lacunarity = 2.0345f; |
float increment = 1.0f; |
float octaves = 1.0f; |
float roughness = 1.00f; |
float ir = (float)index / (float)(vertex_count); |
int2 di = (int2){ tx, ty }; |
float2 vt = GetGridCoordinates(index, grid_resolution); |
float2 vs = (float2){ 1.0f / (float)(grid_resolution.x), 1.0f / (float)(grid_resolution.y) }; |
float2 ve = (float2){ (float)grid_resolution.x, (float)grid_resolution.y }; |
float2 uv = vt * vs; |
float4 position = ComputeRadialGridPosition(uv, vt, ve, camera_position, camera_rotation, camera_view, camera_left, camera_fov); |
float4 bias = (float4){ phase, 0.0f, phase, 0.0f }; |
float4 sample = position + bias; |
float4 noise = RotatedSimplexNoise2dfs(sample.xz * frequency, 35.0f); |
float displacement = noise.x; |
float4 normal = (float4){ 0.0f, 1.0f, 0.0f, 1.0f }; |
float4 vertex = sample + (amplitude * displacement * normal); |
vertex.w = 1.0f; |
normal = (float4){ noise.y, 1.0f, noise.z, 1.0f }; |
normal = normalize(normal); |
vertices[index] = vertex; |
normals[index] = normal; |
texcoords[index] = uv; |
} |
Copyright © 2011 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2011-01-12