Skip to content

Instantly share code, notes, and snippets.

@mirichi

mirichi/RayMarching.rb Secret

Created Mar 7, 2017
Embed
What would you like to do?
レイマーチングテスト
require 'dxruby'
hlsl = <<EOS
float4x4 g_proj, g_view;
struct VS_INPUT // 頂点シェーダの入力フォーマット
{
float4 vPosition : POSITION0;
float2 vTexCoord : TEXCOORD0;
};
struct VS_OUTPUT // 頂点シェーダの出力フォーマット
{
float4 vPosition : POSITION0;
float2 vTexCoord : TEXCOORD0;
};
VS_OUTPUT VS(VS_INPUT v) // 頂点シェーダ
{
VS_OUTPUT output;
output.vPosition = mul(mul(v.vPosition, g_view), g_proj);
output.vTexCoord = v.vTexCoord;
return output;
}
struct PS_INPUT
{
float2 vTexCoord : TEXCOORD0;
};
struct PS_OUTPUT
{
float4 vColor : COLOR0;
};
float3 mod(float3 a, float b) { return a-b*floor(a/b); }
float DistanceFunction(float3 pos)
{
float c = 8.0;
return length(mod(pos, c) - 0.5 * c) - 1.0;
}
float3 getNormal(float3 p)
{
float d = 0.0001;
return normalize(float3( DistanceFunction(p+float3(d,0.0,0.0))-DistanceFunction(p+float3(-d,0.0,0.0)),
DistanceFunction(p+float3(0.0,d,0.0))-DistanceFunction(p+float3(0.0,-d,0.0)),
DistanceFunction(p+float3(0.0,0.0,d))-DistanceFunction(p+float3(0.0,0.0,-d))));
}
PS_OUTPUT PS(PS_INPUT p)
{
PS_OUTPUT output;
float2 pos = (p.vTexCoord * 2.0 - 1.0) * float2(640.0 / 480.0, -1.0);
float3 light = float3(1, 1, -1);
float3 camPos = float3(0.0, 0.0, -3.0);
float3 camDir = float3(0.0, 0.0, 1.0);
float3 camUp = float3(0.0, 1.0, 0.0);
float3 camSide = cross(camUp, camDir);
float focus = 1.8;
float3 rayDir = normalize(camSide*pos.x + camUp*pos.y + camDir*focus);
float t = 0.0, d;
float3 posOnRay = camPos;
for(int i=0; i<32; ++i)
{
d = DistanceFunction(posOnRay);
t += d;
posOnRay = camPos + t*rayDir;
}
if(abs(d) < 0.001)
{
float3 normal = getNormal(posOnRay);
output.vColor = float4(float3(1,1,1) * max(dot(normal, light), 0.2),1);
}
else
{
output.vColor = float4(0,0,0,0);
}
return output;
}
technique
{
pass
{
VertexShader = compile vs_3_0 VS();
PixelShader = compile ps_3_0 PS();
}
}
EOS
width = 640
height = 480
core = Shader::Core.new(hlsl,
g_view: :float,
g_proj: :float)
shader = Shader.new(core)
# 2D用ビュー行列
shader.g_view = [ 1, 0, 0, 0,
0, -1, 0, 0,
0, 0, 1, 0,
-width/2, height/2, 0, 1]
# 2D用透視変換(?)行列
shader.g_proj = [2.0 / width, 0, 0, 0,
0, 2.0 / height, 0, 0,
0, 0, 0, 0,
0, 0, 1, 1]
image = Image.new(640, 480)
Window.loop do
Window.draw_shader(0, 0, image, shader)
break if Input.key_push?(K_ESCAPE)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment