asi*_*mes 4 processing glsl webgl
我在Processing(Java)中编写了一个简单的Sphere Tracer,并将其移植到WebGL/GLSL.当我在处理写我有一个基类Shape并将其扩展为特定的形状,例如Box,Plane,Sphere等每个特定的形状已经那名相关的它,例如成员Sphere的实例有半径,Box实例有长度矢量,等另外每个都具有形状特定的距离函数.
不幸的是我不能在GLSL中使用这样的类,所以我创建了一个struct可以表示任何形状的单词(我在Object下面引用它):
struct Object {
vec3 pos, len, nDir;
float rad;
} objects[4];
Run Code Online (Sandbox Code Playgroud)
然后我为每种形状写了一个距离函数:
float boxSignedDist(Object inBox, vec3 inPos) {
vec3 boxDelta = abs(inPos-inBox.pos)-inBox.len;
return min(max(boxDelta.x, max(boxDelta.y, boxDelta.z)), 0.0)+length(max(boxDelta, 0.0));
}
float planeSignedDist(Object inPlane, vec3 inPos) {
return dot(inPos-inPlane.pos, inPlane.nDir);
}
float roundBoxUnsignedDist(Object inRoundBox, vec3 inPos) {
return length(max(abs(inPos-inRoundBox.pos)-inRoundBox.len, 0.0))-inRoundBox.rad;
}
float sphereSignedDist(Object inSphere, vec3 inPos) {
return length(inPos-inSphere.pos)-inSphere.rad;
}
Run Code Online (Sandbox Code Playgroud)
现在我遇到了一个不同的问题,即用另一个函数(如旋转)包装形状特定的距离函数,如何在GLSL中有效地完成这一操作并不明显.我添加了一个成员Object,int type然后#define为我支持的每个形状做了几个:
#define BOX_SIGNED 1
#define PLANE_SIGNED 2
#define ROUNDBOX_UNSIGNED 3
#define SPHERE_SIGNED 4
struct Object {
int type;
vec3 pos, len, nDir;
float rad;
} objects[4];
Run Code Online (Sandbox Code Playgroud)
所以现在我可以将旋转包装器编写为这样的距离函数:
float rotateY(Object inObject, vec3 inPos, float inRadians) {
inPos -= inObject.pos;
inObject.pos = vec3(0.0, 0.0, 0.0);
float cRad = cos(inRadians);
float sRad = sin(inRadians);
if (inObject.type == BOX_SIGNED)
return boxSignedDist(inObject, vec3(cRad*inPos.x-sRad*inPos.z, inPos.y, cRad*inPos.z+sRad*inPos.x));
else if (inObject.type == PLANE_SIGNED)
return planeSignedDist(inObject, vec3(cRad*inPos.x-sRad*inPos.z, inPos.y, cRad*inPos.z+sRad*inPos.x));
else if (inObject.type == ROUNDBOX_UNSIGNED)
return roundBoxUnsignedDist(inObject, vec3(cRad*inPos.x-sRad*inPos.z, inPos.y, cRad*inPos.z+sRad*inPos.x));
else if (inObject.type == SPHERE_SIGNED)
return sphereSignedDist(inObject, vec3(cRad*inPos.x-sRad*inPos.z, inPos.y, cRad*inPos.z+sRad*inPos.x));
else
return 0.0;
}
Run Code Online (Sandbox Code Playgroud)
看来这是必要的,有没有更好的方法呢?如果rotateY能够接收一个函数指针来调用适当的函数而不是全部函数,那将是很好的else if
GLSL确实是一种非常有限的语言.编译器在优化某些事情方面做得很好,但并不完美.
要记住的一些事项:
int[4]阵列采用相同的存储器中,作为vec4[4]阵列.你Object应该vec3用floats 组.if (type == ...代码可以通过inPos预先构造旋转来改进,但我无法看到if-statements的方法.也许您可以为每个对象类型(或使用宏)编写函数的排列并分别跟踪批量类型?您可能会看到一些好的想法,看看人们为https://www.shadertoy.com/撰写的内容.
最后,GLSL 子例程具有与函数指针类似的意图,但在全局范围内用于所有着色器执行,并且在这里没有帮助.
| 归档时间: |
|
| 查看次数: |
1423 次 |
| 最近记录: |