超级简单的光线追踪
Super simple ray tracing
我正在努力了解使用 GLSL 的简单光线追踪技术。
我参考了 Inigo Quilez 的教程,[link] http://www.iquilezles.org/blog/?p=1521
我的代码编译正确,没有错误,但没有产生预期的球体输出。输出图像全黑。我似乎不知道如何解决这个问题。
#ifdef GL_ES
precision highp float;
#endif
uniform vec3 unResolution;
uniform float time;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform sampler2D fft;
uniform vec4 unPar;
uniform vec4 unPos;
uniform vec4 unBeatBassFFT;
float iSphere( in vec3 ro, in vec3 rd, in vec4 sph )
{
// sphere centered at origin
// |ro|^2 + t^2 + 2<ro,rd>t - r^2 = 0
vec3 oc = ro - sph.xyz;
float b = 2.0*dot( oc,rd );
float c = 2.0*dot( oc,oc );
float h = b*b - sph.w*sph.w;
if ( h<0.0 ) return -1.0;
float t = (-b - sqrt(h))/2.0;
return t;
}
vec3 nSphere( in vec3 pos, in vec4 sph )
{
return (pos-sph.xyz)/sph.w;
}
float iPlane( in vec3 ro, in vec3 rd )
{
return -ro.y/rd.y;
}
vec3 nPlane( in vec3 pos )
{
return vec3(0.0,1.0,0.0);
}
vec4 sph1 = vec4( 0.0, 1.0, 0.0, 1.0 );
float intersect( in vec3 ro, in vec3 rd, out float resT )
{
resT = 1000.0;
float id = -1.0;
float tsph = iSphere( ro, rd, sph1 );
float tpla = iPlane( ro, rd );
if ( tsph>0.0 )
{
id = 1.0;
resT = tsph;
}
if (tpla>0.0 && tpla<resT)
{
id = 2.0;
resT = tpla;
}
return id;
}
void main(void)
{
vec3 light = normalize( vec3( 0.57703 ));
vec2 uv = (gl_FragCoord.xy/unResolution.xy)*vec2(1.78,1.0);
//sph1.x = 0.5*cos(time);
//sph1.z = 0.5*sin(time);
vec3 ro = vec3( 0.0, 0.5, 3.0 );
vec3 rd = normalize( vec3( (-1.0+2.0+uv)*vec2(1.78,1.0), 1.0 ) );
float t;
float id = intersect( ro, rd, t );
vec3 col = vec3(0.0);
if( id>0.5 && id<1.5 )
{
vec3 pos = ro + t*rd;
vec3 nor = nSphere( pos, sph1 );
float dif = clamp(dot( nor, light ), 0.0, 1.0);
float ao = 0.5 + 0.5*nor.y;
float amb = 0.5 + 0.5*nor.y;
col = vec3( 0.9, 0.8, 0.6 )*dif+amb*vec3(0.5,0.6,0.7);
}
else if( id>1.5 )
{
vec3 pos = ro + t*rd;
vec3 nor = nPlane( pos );
float dif = clamp( dot(nor, light), 0.0, 1.0 );
float amb = smoothstep( 0.0, 2.0*sph1.w, length(pos.xz-sph1.xz) );
col = vec3(amb*0.7);
//col = vec3( 1.0, 0.0, 0.0 )*dif + amb*vec3(0.5,0.6,0.7);
}
col = sqrt(col);
gl_FragColor = vec4(col,1.0);
}
编辑:以下是根据@LJᛃ 的回答更新的代码。
为通过搜索引擎找到此 post 的用户添加。
我还没有完善球体的阴影,但这里有一段代码供大家使用!
#ifdef GL_ES
precision highp float;
#endif
uniform vec2 resolution;
#define unResolution resolution
uniform float time;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform sampler2D fft;
uniform vec4 unPar;
uniform vec4 unPos;
uniform vec4 unBeatBassFFT;
float iSphere( in vec3 ro, in vec3 rd, in vec4 sph )
{
// sphere centered at origin
// |ro|^2 + t^2 + 2<ro,rd>t - r^2 = 0
vec3 oc = ro - sph.xyz;
float b = 2.0*dot( oc,rd );
float c = 2.0*dot( oc,oc );
float h = b*b - sph.w*sph.w;
if ( h<0.0 ) return -1.0;
float t = (-b - sqrt(h))/2.0;
return t;
}
vec3 nSphere( in vec3 pos, in vec4 sph )
{
return (pos-sph.xyz)/sph.w;
}
float iPlane( in vec3 ro, in vec3 rd )
{
return -ro.y/rd.y;
}
vec3 nPlane( in vec3 pos )
{
return vec3(0.0,1.0,0.0);
}
vec4 sph1 = vec4( 0.0, 1.0, 0.0, 1.0 );
float intersect( in vec3 ro, in vec3 rd, out float resT )
{
resT = 1000.0;
float id = -1.0;
float tsph = iSphere( ro, rd, sph1 );
float tpla = iPlane( ro, rd );
if ( tsph>0.0 )
{
id = 1.0;
resT = tsph;
}
if (tpla>0.0 && tpla<resT)
{
id = 2.0;
resT = tpla;
}
return id;
}
void main(void)
{
vec3 light = normalize( vec3( 0.57703 ));
vec2 uv = (gl_FragCoord.xy/unResolution.xy);
vec2 p = uv * 2.0 - 1.0;
p.x*=unResolution.x/unResolution.y;
//sph1.x = 0.5*cos(time);
//sph1.z = 0.5*sin(time);
vec3 ro = vec3( 0.0, 1.0, -1.0 );
vec3 rd = normalize( vec3(p,0.2) );
float t;
float id = intersect( ro, rd, t );
vec3 col = vec3(0.0);
if( id>0.5 && id<1.5 )
{
vec3 pos = ro + t*rd;
vec3 nor = nSphere( pos, sph1 );
float dif = clamp(dot( nor, light ), 0.0, 1.0);
float ao = 0.1 + 0.5*nor.y;
float amb = 0.5 + 0.5*nor.y;
col = vec3( 1.0, 0.0, 0.0 )*dif + amb*vec3(0.5,0.6,0.7);
}
else if( id>1.5 )
{
vec3 pos = ro + t*rd;
vec3 nor = nPlane( pos );
float dif = clamp( dot(nor, light), 0.5, 1.0 );
float amb = smoothstep( 0.5, 2.0*sph1.w, length(pos.xz-sph1.xz) );
col = vec3(amb*0.9);
//col = vec3( 1.0, 0.0, 0.0 )*dif + amb*vec3(0.5,0.6,0.7);
}
col = sqrt(col);
gl_FragColor = vec4(col,1.0);
}
所以我将其移植到 GLSLSandbox.com,我将 unResolution
制服替换为一个 glsl 沙箱提供的制服:
uniform vec2 resolution;
#define unResolution resolution
然后我查看了您对光线来源和方向的基本设置。你试图在 uv 中考虑纵横比的方式是错误的,你想先计算居中坐标,然后应用纵横比变换:
vec2 uv = gl_FragCoord.xy/unResolution.xy;
// p is 0 at the center of the screen, x=-1 on the left, +1 on the right etc.
vec2 p = uv * 2.0 - 1.0;
// account for aspect ratio
p.x*=unResolution.x/unResolution.y;
// substitute uv with p in the following code
此时我看到了我认为是你的地平面的东西,屏幕在灰白色和黑色之间水平分割,所以我稍微调整了一下你的光线原点和方向:
vec3 ro = vec3( 0.0, 1., -1. );
vec3 rd = normalize( vec3( p, .25 ) )
瞧,我们有一个球体:
投影仍然有点奇怪,移动光线原点并不像我期望的那样,但我会把它留给你:)
我正在努力了解使用 GLSL 的简单光线追踪技术。 我参考了 Inigo Quilez 的教程,[link] http://www.iquilezles.org/blog/?p=1521
我的代码编译正确,没有错误,但没有产生预期的球体输出。输出图像全黑。我似乎不知道如何解决这个问题。
#ifdef GL_ES
precision highp float;
#endif
uniform vec3 unResolution;
uniform float time;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform sampler2D fft;
uniform vec4 unPar;
uniform vec4 unPos;
uniform vec4 unBeatBassFFT;
float iSphere( in vec3 ro, in vec3 rd, in vec4 sph )
{
// sphere centered at origin
// |ro|^2 + t^2 + 2<ro,rd>t - r^2 = 0
vec3 oc = ro - sph.xyz;
float b = 2.0*dot( oc,rd );
float c = 2.0*dot( oc,oc );
float h = b*b - sph.w*sph.w;
if ( h<0.0 ) return -1.0;
float t = (-b - sqrt(h))/2.0;
return t;
}
vec3 nSphere( in vec3 pos, in vec4 sph )
{
return (pos-sph.xyz)/sph.w;
}
float iPlane( in vec3 ro, in vec3 rd )
{
return -ro.y/rd.y;
}
vec3 nPlane( in vec3 pos )
{
return vec3(0.0,1.0,0.0);
}
vec4 sph1 = vec4( 0.0, 1.0, 0.0, 1.0 );
float intersect( in vec3 ro, in vec3 rd, out float resT )
{
resT = 1000.0;
float id = -1.0;
float tsph = iSphere( ro, rd, sph1 );
float tpla = iPlane( ro, rd );
if ( tsph>0.0 )
{
id = 1.0;
resT = tsph;
}
if (tpla>0.0 && tpla<resT)
{
id = 2.0;
resT = tpla;
}
return id;
}
void main(void)
{
vec3 light = normalize( vec3( 0.57703 ));
vec2 uv = (gl_FragCoord.xy/unResolution.xy)*vec2(1.78,1.0);
//sph1.x = 0.5*cos(time);
//sph1.z = 0.5*sin(time);
vec3 ro = vec3( 0.0, 0.5, 3.0 );
vec3 rd = normalize( vec3( (-1.0+2.0+uv)*vec2(1.78,1.0), 1.0 ) );
float t;
float id = intersect( ro, rd, t );
vec3 col = vec3(0.0);
if( id>0.5 && id<1.5 )
{
vec3 pos = ro + t*rd;
vec3 nor = nSphere( pos, sph1 );
float dif = clamp(dot( nor, light ), 0.0, 1.0);
float ao = 0.5 + 0.5*nor.y;
float amb = 0.5 + 0.5*nor.y;
col = vec3( 0.9, 0.8, 0.6 )*dif+amb*vec3(0.5,0.6,0.7);
}
else if( id>1.5 )
{
vec3 pos = ro + t*rd;
vec3 nor = nPlane( pos );
float dif = clamp( dot(nor, light), 0.0, 1.0 );
float amb = smoothstep( 0.0, 2.0*sph1.w, length(pos.xz-sph1.xz) );
col = vec3(amb*0.7);
//col = vec3( 1.0, 0.0, 0.0 )*dif + amb*vec3(0.5,0.6,0.7);
}
col = sqrt(col);
gl_FragColor = vec4(col,1.0);
}
编辑:以下是根据@LJᛃ 的回答更新的代码。 为通过搜索引擎找到此 post 的用户添加。
我还没有完善球体的阴影,但这里有一段代码供大家使用!
#ifdef GL_ES
precision highp float;
#endif
uniform vec2 resolution;
#define unResolution resolution
uniform float time;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform sampler2D fft;
uniform vec4 unPar;
uniform vec4 unPos;
uniform vec4 unBeatBassFFT;
float iSphere( in vec3 ro, in vec3 rd, in vec4 sph )
{
// sphere centered at origin
// |ro|^2 + t^2 + 2<ro,rd>t - r^2 = 0
vec3 oc = ro - sph.xyz;
float b = 2.0*dot( oc,rd );
float c = 2.0*dot( oc,oc );
float h = b*b - sph.w*sph.w;
if ( h<0.0 ) return -1.0;
float t = (-b - sqrt(h))/2.0;
return t;
}
vec3 nSphere( in vec3 pos, in vec4 sph )
{
return (pos-sph.xyz)/sph.w;
}
float iPlane( in vec3 ro, in vec3 rd )
{
return -ro.y/rd.y;
}
vec3 nPlane( in vec3 pos )
{
return vec3(0.0,1.0,0.0);
}
vec4 sph1 = vec4( 0.0, 1.0, 0.0, 1.0 );
float intersect( in vec3 ro, in vec3 rd, out float resT )
{
resT = 1000.0;
float id = -1.0;
float tsph = iSphere( ro, rd, sph1 );
float tpla = iPlane( ro, rd );
if ( tsph>0.0 )
{
id = 1.0;
resT = tsph;
}
if (tpla>0.0 && tpla<resT)
{
id = 2.0;
resT = tpla;
}
return id;
}
void main(void)
{
vec3 light = normalize( vec3( 0.57703 ));
vec2 uv = (gl_FragCoord.xy/unResolution.xy);
vec2 p = uv * 2.0 - 1.0;
p.x*=unResolution.x/unResolution.y;
//sph1.x = 0.5*cos(time);
//sph1.z = 0.5*sin(time);
vec3 ro = vec3( 0.0, 1.0, -1.0 );
vec3 rd = normalize( vec3(p,0.2) );
float t;
float id = intersect( ro, rd, t );
vec3 col = vec3(0.0);
if( id>0.5 && id<1.5 )
{
vec3 pos = ro + t*rd;
vec3 nor = nSphere( pos, sph1 );
float dif = clamp(dot( nor, light ), 0.0, 1.0);
float ao = 0.1 + 0.5*nor.y;
float amb = 0.5 + 0.5*nor.y;
col = vec3( 1.0, 0.0, 0.0 )*dif + amb*vec3(0.5,0.6,0.7);
}
else if( id>1.5 )
{
vec3 pos = ro + t*rd;
vec3 nor = nPlane( pos );
float dif = clamp( dot(nor, light), 0.5, 1.0 );
float amb = smoothstep( 0.5, 2.0*sph1.w, length(pos.xz-sph1.xz) );
col = vec3(amb*0.9);
//col = vec3( 1.0, 0.0, 0.0 )*dif + amb*vec3(0.5,0.6,0.7);
}
col = sqrt(col);
gl_FragColor = vec4(col,1.0);
}
所以我将其移植到 GLSLSandbox.com,我将 unResolution
制服替换为一个 glsl 沙箱提供的制服:
uniform vec2 resolution;
#define unResolution resolution
然后我查看了您对光线来源和方向的基本设置。你试图在 uv 中考虑纵横比的方式是错误的,你想先计算居中坐标,然后应用纵横比变换:
vec2 uv = gl_FragCoord.xy/unResolution.xy;
// p is 0 at the center of the screen, x=-1 on the left, +1 on the right etc.
vec2 p = uv * 2.0 - 1.0;
// account for aspect ratio
p.x*=unResolution.x/unResolution.y;
// substitute uv with p in the following code
此时我看到了我认为是你的地平面的东西,屏幕在灰白色和黑色之间水平分割,所以我稍微调整了一下你的光线原点和方向:
vec3 ro = vec3( 0.0, 1., -1. );
vec3 rd = normalize( vec3( p, .25 ) )
瞧,我们有一个球体:
投影仍然有点奇怪,移动光线原点并不像我期望的那样,但我会把它留给你:)