OpenCL

VEXユーザ向けのOpenCL

構文逆引き

floatでabs fabs
剰余(floatで) fmod
剰余 %
exp eを底する指数関数計算
2x2(mat4) と 2 の掛け算 mat2vecmul( float4 , float2 ) //#import “matrix.h”
3Dの軸回転 q.xy = mat2vecmul( tyb_rot2D( T ) , q.xy );
fract fract( x ) = mod( x , 1.0f );

サンプルコード

UV(左下が0,0⇒右上が1,1)

float2 uv = (float2)(@ixy.x,@ixy.y) / (float2)(@res.x,@res.y);

UV(中心が0,0)

float2 uv = (float2)((2.0f*@ixy.x - @res.x)/@res.y,(2.0f*@ixy.y - @res.y)/@res.y);

GLSLのmodを再現

float glMod(float x, float y){
    return x - y * floor(x / y);
}

タイリング

float2 tile(float2 _p,float _repeat){
  _p *= _repeat;
  float intpart;
  float fx = fract(_p.x, &intpart);
  float fy = fract(_p.y, &intpart);
  return (float2)(fx,fy);
}

2D回転

float2 rotate2d(float2 pt, float angle_rad){
    float c = cos(angle_rad);
    float s = sin(angle_rad);
    return (float2)(
        pt.x * c - pt.y * s,
        pt.x * s + pt.y * c
    );
}

自作ライブラリ関数

#bind layer src float3
#bind layer !&dst float3

#import "matrix.h"
#import "任意のパスでオリジナルのライブラリも読める/tyb.h"

#define ITERATIONS 128.0f

//Distance to the scene
float map(float3 p,float T){
    float3 spherePos = (float3)(sin(T)*3.0,0,0);
    float sphere = tyb_Sphere(p - spherePos,0.25f);
    
    //回転のサンプル
    float3 q = p;
    q.y -= T * 2.0f;
    q.xy = mat2vecmul(tyb_rot2D(T*0.25),q.xy);
        
    //繰り返しのfractと位置補正
    q = tyb_fract3(q) - (float3)(0.5,0.5,0.5);
    
    //繰り返しのスペーシング
    q.xy = ( tyb_fract2(q.xy) - (float2)(0.5,0.5));
    q.z = fmod(q.z,0.275f) - 0.125;
    
    //最後に割っているのは掛け算と同値で、表示バグを回避するためのもの
    float box = tyb_Box(q * 6.1f,(float3)(0.75,0.75,0.75)) / 6.1f;
    float ground = q.y + 0.65;
    return min(ground,tyb_sMin(sphere,box,0.85));
}

@KERNEL
{
    float T = (float)(@Time);   
    //ray marchの時のuv設定
    float2 uv = ((float2)(@ixy.x,@ixy.y) * (float2)(2.0f,2.0f) - (float2)(@res.x,@res.y)) / (float2)(@res.y,@res.y);
    // Initialization
    //ray origin = カメラ位置
    float3 ro = (float3)(sin(T), 0.0f, -3.0f);

    //ray direction = 光源方向 uv を使うことで各ピクセルが画面の中心から広がる固有の光線方向を持つようになる
    float3 rd = normalize((float3)(uv.x,uv.y, 1.0f));
    
    //final pixel color
    float3 col = (float3)(0.0f,0.0f,0.0f);
    float3 col2 = @src;
        
    //total distance travelled ポイントがカメラの原点から移動した現在の距離を追跡する。初期値は0 ray marchのmarch
    float t = 0.0f;
    
    //Raymarching
    for(float i=0.0f;i<ITERATIONS;i+=1.0f){
        //オブジェクトに当たるまでループするところ
        float3 p = ro + rd * (float3)(t,t,t);
        
        //ゆがみ
        p.xy = mat2vecmul(tyb_rot2D(T*0.25),p.xy);
        p.y += sin(t+T*2.5)*0.435f;
        
        //position along the ray 光が進んだ
        float d = map(p,T);
        
        //"march" the ray
        t += d;
        
        //"march"が細かくなって意味ないところを進み過ぎないように制限
        //tもあまりに遠いところに行って意味なくならないように
        col = (float3)(i,i,i) / (float3)(ITERATIONS,ITERATIONS,ITERATIONS);
        if(d<0.001f || t>100.0f) break;

    }    
    
    //t = Zbuffer
    t*=.15;
    //色付け
    col = tyb_palette(t,(float3)(0.25,0.25,0.75),(float3)(0.25,0.5,0.75),(float3)(0.25,0.5,1.0),(float3)(0.2,0.1,0.5));
    @dst.set(col);

}

カーネル登録

#bind layer src? val=0
#bind layer !&dst float3

?:オプションか否か