金属 - 颠倒的场景

时间:2017-02-05 02:27:49

标签: glsl metal

我正在尝试将此glsl转换为我的Metal应用以用于学习目的。它可以成功渲染。但是,有两个问题:

  1. 场景颠倒了。

  2. 我用鼠标旋转相机。当我移动鼠标时,场景旋转到完全看不见的角度。

  3. 我认为这两个问题是相关的,我该如何解决这个问题?以下是我的Metal代码:

    #include <metal_stdlib>
    using namespace metal;
    
    constant const float gtime = 0.0;//<-- stop the animation for now.
    constant const float pi = 3.141592653589793;
    
    
    float sdPlane( float3 p) {
        return p.y + 0.4;
    }
    
    float sdSphere( float3 p,  float r) {
        return length(p) - r;
    }
    
    float sdCapsule( float3 p, float3 a, float3 b, float r ) {
        float3 pa = p - a, ba = b - a;
        float h = clamp( dot(pa, ba) / dot(ba , ba), 0.0, 1.0 );
        return length( pa - ba * h ) - r;
    }
    
    float motor(float _min, float _max, float time) {
        float t = 0.5 + 0.5 * sin(time);
        return mix(_min, _max, t);
    }
    
    float3 rotate_from_origin(float3 origin, float3 target, float r, float angle) {
        return float3(
                    origin.x + r * cos(angle),
                    origin.y + r * sin(angle),
                    target.z
                    );
    }
    
    float3 preserve(float3 p0, float3 p1, float len) {
        float3 v = p1 - p0;
        float3 u = normalize(v);
        return p0 + len * u;
    }
    
    float smin( float a, float b, float k ) {
        float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
        return mix( b, a, h ) - k*h*(1.0-h);
    }
    
    float2 smin2( float2 a, float2 b, float k ) {
        float h = clamp( 0.5+0.5*(b.x-a.x)/k, 0.0, 1.0 );
        return mix( b, a, h ) - k*h*(1.0-h);
    }
    
    float2 map( float3 p) {
        float t = gtime * 2.0;
        float cx = 0.2;
        float cz = 0.1;
        float3 p0 = float3(-cx, 0.0, 0.0);
        float3 p1 = float3(-cx, -0.2, -cz);
        float3 p2 = float3(-cx, -0.4, -cz);
        float3 p3 = float3(-cx, 0.2, cz);
        float3 p4 = float3(-cx, -0.4, cz);
    
        float3 p5 = float3(cx, 0.0, 0.0);
        float3 p6 = float3(cx, -0.2, -cz);
        float3 p7 = float3(cx, -0.4, -cz);
        float3 p8 = float3(cx, 0.2, cz);
        float3 p9 = float3(cx, -0.4, cz);
    
        float3 p10 = float3(0.0, 0.0, 0.0);
        float3 p11 = float3(cx, -0.2, 0.0);
    
        float angle0 = 0.0;
        float angle1 = 0.0;
        p0.y = -motor(-0.05, 0.05, t * 4.0);
        angle0 = -motor(pi * 0.15, pi * 0.65, t * 2.0 - pi * 0.5);
        angle1 = -motor(pi * 0.15, pi * 0.65, t * 2.0 + pi * 0.5);
        p1 = rotate_from_origin(p0, p1, 0.2, pi-angle0);
        p3 = rotate_from_origin(p0, p3, 0.2, pi-angle1);
        angle0 += -motor(0.0, pi * 0.5, t * 2.0 + pi);
        angle1 += -motor(0.0, pi * 0.5, t * 2.0 + pi + pi);
        p2 = rotate_from_origin(p1, p2, 0.2, pi-angle0*0.6);
        p4 = rotate_from_origin(p3, p4, 0.2, pi-angle1*0.6);
    
        p5.y = -motor(-0.05, 0.05, t * 4.0);
        angle0 = -motor(pi * 0.15, pi * 0.65, t * 2.0 - pi * 0.5);
        angle1 = -motor(pi * 0.15, pi * 0.65, t * 2.0 + pi * 0.5);
        p6 = rotate_from_origin(p5, p6, 0.2, angle0);
        p8 = rotate_from_origin(p5, p8, 0.2, angle1);
        angle0 += -motor(0.0, pi * 0.5, t * 2.0 + pi);
        angle1 += -motor(0.0, pi * 0.5, t * 2.0 + pi + pi);
        p7 = rotate_from_origin(p6, p7, 0.2, angle0*0.6);
        p9 = rotate_from_origin(p8, p9, 0.2, angle1*0.6);
    
        p10.y = -motor(-0.02, 0.02, t * 4.0 - pi * 0.5);
        p11 = preserve(p5, p11, -0.25);
        float w = 0.05;
    
        float2 dd = float2(sdPlane(p - float3(0.0, -0.05, 0.0)), 1.0);
    
        float2 d = float2(10.0);
        d = smin2(d, float2(sdCapsule(p, p0, p1, w), 30.0), 0.001);
        d = smin2(d, float2(sdCapsule(p, p1, p2, w), 30.0), 0.001);
        d = smin2(d, float2(sdCapsule(p, p0, p3, w), 40.0), 0.001);
        d = smin2(d, float2(sdCapsule(p, p3, p4, w), 40.0), 0.001);
    
        d = smin2(d, float2(sdCapsule(p, p5, p6, w), 30.0), 0.001);
        d = smin2(d, float2(sdCapsule(p, p6, p7, w), 30.0), 0.001);
        d = smin2(d, float2(sdCapsule(p, p5, p8, w), 40.0), 0.001);
        d = smin2(d, float2(sdCapsule(p, p8, p9, w), 40.0), 0.001);
    
        d = smin2(d, float2(sdCapsule(p, p0, p10, w + 0.0025 * sin(p.x * pi * 60.0)), 90.0), 0.1);
        d = smin2(d, float2(sdCapsule(p, p10, p5, w), 90.0), 0.1 + 0.8*(0.5 + 0.5 * sin(gtime * 0.2)));
    
        d = smin2(d, float2(sdCapsule(p, p5, p11, w), 90.0), 0.15);
    
        d = smin2(d, dd, 0.01);
        return d;
    }
    
    float3 calcNormal( float3 p) {
        float2 e = float2(-1.0, 1.0) * 0.001;
        float3 nor = normalize(
                             e.xyy * map(p + e.xyy).x +
                             e.yxy * map(p + e.yxy).x +
                             e.yyx * map(p + e.yyx).x +
                             e.xxx * map(p + e.xxx).x
                             );
        return nor;
    }
    
    float2 castRay( float3 ro,  float3 rd,  float maxt) {
        float precis = 0.001;
        float h = precis * 2.0;
        float t = 0.0;
        float m = -1.0;
        for(int i = 0; i < 60; i++) {
            if(abs(h) < precis || t > maxt) continue;
            float2 res = map(ro + rd * t);
            h = res.x;
            t += h;
            m = res.y;
        }
        if(t > maxt) m = -1.0;
        return float2(t, m);
    }
    
    float softshadow( float3 ro,  float3 rd,  float mint,  float maxt,  float k) {
        float sh = 1.0;
        float t = mint;
        float h = 0.0;
        for(int i = 0; i < 30; i++) {
            if(t > maxt) continue;
            h = map(ro + rd * t).x;
            sh = min(sh, k * h / t);
            t += h;
        }
        return sh;
    }
    
    float3 render( float3 ro,  float3 rd) {
        float3 col = float3(1.0);
        float2 res = castRay(ro, rd, 20.0);
        float t = res.x;
        float m = res.y;
    
        col = 0.45 + 0.3*sin(float3(0.05,0.08,0.10)*(m-1.0)+gtime);
        if(abs(m - 1.0) < 0.01) col = float3(0.5);
    
        float3 pos = ro + rd * t;
    
        float3 nor = calcNormal(pos);
        float3 lig = normalize(float3(-0.4, 0.7, 0.5));
        float dif = clamp(dot(lig, nor), 0.0, 1.0);
        float spe = pow(clamp(dot(reflect(rd, nor), lig), 0.0, 1.0), 64.0);
        float fre = 1.0 - dot(-rd, nor);
        float sh = softshadow(pos, lig, 0.02, 20.0, 7.0);
        col = 1.0*col * (dif + spe + fre * 0.5) * (0.5 + sh * 0.5);
    
        return col;
    }
    
    kernel void compute(texture2d<float, access::write> output [[texture(0)]],
                        constant float &time [[buffer(1)]],
                        constant float &mouseX [[buffer(2)]],
                        constant float &mouseY [[buffer(3)]],
                        uint2 gid [[thread_position_in_grid]]) {
    
        int width = output.get_width();
        int height = output.get_height();
        float2 uv = float2(gid) / float2(width, height);
        float2 p = uv * 2.0 - 1.0;
    
        p.x *= width / height;
    
        float2 ms = 2.0 * float2(mouseX,mouseY) - 1.0;
    
        float3 ro = float3(ms.x * 2.0, 2.0 - ms.y, 1.5);
        float3 ta = float3(0.0, 0.0, 0.0);
        float3 cw = normalize(ta - ro);
        float3 cp = float3(0.0, 1.0, 0.0);
        float3 cu = normalize(cross(cw, cp));
        float3 cv = normalize(cross(cu, cw));
        float3 rd = normalize(p.x * cu + p.y * cv + 2.5 * cw);
        float3 col = render(ro, rd);
    
        output.write(float4(col, 1.), gid);
    }
    

1 个答案:

答案 0 :(得分:2)

根据Marius的评论,我发现了解决方案。我只是通过添加y来反转-值,然后一切都恢复正常:

float2 ms = 2.0 * normalize(float2(mouseX,-mouseY)) - 1.0;//<-- make mouseY negative