【发布时间】:2015-12-26 07:27:50
【问题描述】:
我编写了一个片段着色器,它使用简单的光线追踪在片段着色器内渲染一个球体,对形状进行漫反射。我可以让它适用于一个领域;但是,当我尝试制作多个球体时,只能看到一个。在着色器的 main() 函数中,我基本上执行了与我为要制作的每个附加球体渲染一个球体相同的过程,但这似乎目前不起作用。
附加信息:
球体的顶点 (x,y,z,r) 可以通过以下方式找到:
x 和 y 的顶点位置(即float x = vPosition.x;
和float y = vPosition.y;)。 z 的顶点位置是使用下面代码中的computeZ() 函数计算的。最后,对于 sphere.r,我使用了光线的原点顶点 (V) + 光线的方向 (W)。光线本身从原点射入屏幕,并根据球体是否击中球体来确定球体的颜色(我在raySphere() 中有执行此操作的功能代码。
我想我只需要在 main 中创建一个数组来存储球体,然后创建一个 for 循环来为数组中的每个球体调用 raySphere() 和 shadeSphere() 函数(这是我最初尝试过的,但是它没有工作)。
主要是,在初始化一个球体的顶点位置以及射线的 V 和 W 之后,我有一个 if 语句来检查 z 是否大于 0,这意味着着色器当前位于球体内部,因此它可以继续阴影,否则什么也不做。由于以这种方式定义球体的边界,我不确定如何使用我之前提到的 for 循环解决方案将相同的逻辑应用于多个球体。同样在 main 中,我检查 t 值(对于每个球体)是否小于 10000,如果是,则调用 shadeSphere() 函数对球体进行着色;但是,我目前的逻辑也不适用于多个领域。 turbulence 和 fractal 函数只是添加程序纹理,它们很长,所以我不会添加它们的代码。
制作多个球体的正确方法是什么?
编辑:
*似乎球体是在彼此之上渲染的,因为我有一个 if 语句为每个球体设置 gl_FragColor 并且实际渲染的唯一颜色是最后一个语句中设置的颜色(见代码末尾)
我有下面的相关代码:
<script src=lib1.js></script>
<body bgcolor=black>
<center>
<td><canvas id='canvas1' width=550 height=550></canvas></td>
</center>
</body>
<script id='my_vertex_shader' type='x-shader/x-vertex'>
attribute vec3 aPosition;
varying vec3 vPosition;
void main() {
gl_Position = vec4(aPosition, 1.0);
vPosition = aPosition;
}
</script>
<script id='my_fragment_shader' type='x-shader/x-fragment'>
precision mediump float;
uniform float uTime;
uniform vec3 uCursor;
varying vec3 vPosition;
vec4 sphere;
vec4 sphere2;
vec3 material;
vec3 Lrgb;
vec3 Ldir;
float computeZ(vec2 xy, float r) {
float zz = (r * r - xy.x * xy.x - xy.y * xy.y)/.5;
if (zz < 0.)
return -1.;
else
return sqrt(zz);
}
// Compute intersection of a ray with a sphere, if any. Return t.
// If there is no intersection, return 10000.
float raySphere(vec3 V, vec3 W, vec4 sph) {
//float r = 1.0;
//float b = 2.0* dot(V,W);
//float c = dot(V, V) - (sph.w * sph.w);
//float h = b*b - 4.0*c;
//float t = (-b - sqrt(h))/2.0;
//if(h <0.0 || t < 0.0 ) return 10000.;
//return t;
float b = 2.0 * dot(V -= sph.xyz, W);
float c = dot(V, V) - sph.w * sph.w;
float d = b * b - 4.0 * c;
return d < 0.0 ? 10000. : (-b - sqrt(d)) / 2.0;
}
// Diffusely shade a sphere.
// point is the x,y,z position of the surface point.
// sphere is the x,y,z,r definition of the sphere.
// material is the r,g,b color of the sphere.
//vec3 shadeSphere(vec3 point, vec4 sphere, vec3 material, float s) {
vec3 shadeSphere(vec3 point, vec4 sphere, vec3 material) {
vec3 color = vec3(1.,2.,4.);
vec3 N = (point - sphere.xyz) / sphere.w;
float diffuse = max(dot(Ldir, N), 0.0);
vec3 ambient = material/5.0;
//color = ambient + Lrgb *s *diffuse * max(0.0, dot(N , Ldir));
color = ambient + Lrgb * diffuse * max(0.0, dot(N , Ldir));
return color;
}
void main(void) {
vec2 c = uCursor.xy;
Lrgb = vec3(1.,.5,0.);
Ldir = normalize(vec3(c.x, c.y, 1. - 2. * dot(c, c)));
float x = vPosition.x;
float y = vPosition.y;
float z = computeZ(vPosition.xy, 1.0);
// COMPUTE V AND W TO CREATE THE RAY FOR THIS PIXEL,
// USING vPosition.x AND vPosition.y.
vec3 V, W;
W = normalize(vec3( 2.0,0.0,1.0 ));
vec4 spheres[3];
if(z > 0.){
//sphere = vec4(x,y,z,V + dot(W,vec3(1.,1.,1.)));
//sphere2 = vec4(x+10.,y+10.,z+10.,V + dot(W,vec3(1.,1.,1.)));
vec2 uv = vPosition.xy/uCursor.xy;
//generate a ray
//V = vec3(0.0, 1.0, 3.0);
//W = normalize(vec3((-1.0 + 2.0 )*vec2(1.78,1.0), -1.0));
//SET x,y,z AND r FOR sphere.
//SET r,g,b FOR material.
vec3 material = vec3(4., 1., 3.);
vec3 color = vec3(0., 0., 0.);
float t = 0.;
for(int i = 0; i < 3; i++){
if(i == 0){
V = vec3(2.0,1.0,.0);
spheres[i] = vec4(x,y,z/2.,V + dot(W,vec3(1.,1.,1.)));
float t = raySphere(V, W, spheres[i] );
}
if(i == 1){
V = vec3(100.0,500.0,.0);//attempt to move the vertex of the ray for the second sphere
spheres[i] = vec4(x,y,z/5.,V + dot(W,vec3(1.,1.,1.)));
vec3 shift1 = vec3(30.,30.,30.);
vec3 newPoint = shift1 + V;
float t = raySphere(newPoint, W, spheres[i] );
}
if(i == 2){
V = vec3(500.0,1.0,.0); //attempt to move the vertex of the ray for the third sphere
spheres[i] = vec4(x,y,z/7.,V + dot(W,vec3(1.,1.,1.)));
vec3 shift2 = vec3(50.,50.,50.);
vec3 newPoint2 = shift2 + V;
float t = raySphere(newPoint2, W, spheres[i] );
}
//float t2 = raySphere(V, W, sphere2);
//float s = sin((uTime));
vec3 time = vec3(uTime*2., 1.,1.);
//float s = tan((tan(sphere.z)/tan((time)*.90+200.0)));
if (t < 10000.)
//float s = (sin(sphere.x)/cos(uTime*1.123+200.0));
//if(i == 0)
color = shadeSphere(V + t * W, spheres[i], material);
//if(i == 1)
//color = shadeSphere(V + t1 * W, sphere[i], material);
//if(i == 2)
//color = shadeSphere(V + t1 * W, sphere[i], material);
//color = shadeSphere(V + t1 * W, sphere, material,s);
//if (t2 < 10000.)
//color = shadeSphere(V + t2 * W, sphere, material,s);
color.r = 0.5;
color = pow(color, vec3(.45,.45,.45)); // Do Gamma correction.
//float d = dot(vec3(x,y,z), vec3(1.,1.,1.));
//if (d > 0.)
// s += 0.6 * d;
//gl_FragColor = vec4(color, 1.); // Set opa city to 1.
if(i == 0)
gl_FragColor = vec4((color) * vec3(5.0, 1.0, 4.5), 1.);
if(i == 1)
gl_FragColor = vec4((color) * vec3(1.0, 3.0, 7.5), 1.);
if(i == 2)
gl_FragColor = vec4((color) * vec3(3.0, 4.0, 8.5), 1.);
}
} //Close brace for z-check
}
</script>
球体 3 的图像似乎呈现在其他两个球体之上
【问题讨论】:
-
详细信息在哪里?你如何将球体 x,y,z,r 传递给着色器?你使用什么样的光线追踪(向前,向后,光线的属性是什么......)?我们不知道您的部分代码背后是什么,并且怀疑有人会尝试对其进行解码...通常添加一些描述代码的作用和方式的文本是一个好主意(代码中的 cmets 仅对于那些现在代码应该做什么以及如何做)...
-
@Spektre 是的,很抱歉。我在帖子中添加了一些额外的信息。如果需要任何其他说明,请告诉我。
标签: glsl webgl fragment-shader raytracing