我正在尝试将此glsl转换为我的Metal
应用以用于学习目的。它可以成功渲染。但是,有两个问题:
场景颠倒了。
我用鼠标旋转相机。当我移动鼠标时,场景旋转到完全看不见的角度。
我认为这两个问题是相关的,我该如何解决这个问题?以下是我的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);
}
答案 0 :(得分:2)
根据Marius的评论,我发现了解决方案。我只是通过添加y
来反转-
值,然后一切都恢复正常:
float2 ms = 2.0 * normalize(float2(mouseX,-mouseY)) - 1.0;//<-- make mouseY negative