マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

+αをしてみる

面白いプログラムがあったので+αをしてみた。変更点はシェーダととrubyの部分のlookを変えただけ。とりあえずスクリーンショットを載せる

shaderは以下のようにした。まずは頂点シェーダ

attribute vec3 position;

void main(){
    vec4 pos = gl_ModelViewProjectionMatrix * vec4(position, 1.0);

    gl_FrontColor.r = sin(4 * pos.x);
    gl_FrontColor.g = sin(4 * pos.y);
    gl_FrontColor.b = sin(4 * pos.z);

    gl_Position = pos;
}

なんと頂点シェーダで色を付けて、フラグメントシェーダに渡してしまっている。フラグメントシェーダでは頂点シェーダから受け取った色を出力してるだけ。今回は頂点だけ表示しているからいいけど、面を表示させるなら頂点シェーダでなくフラグメントシェーダで色を決めようね!次はフラグメントシェーダ

void main( void ) {
    gl_FragColor = gl_Color;
}

以下、全プログラム

require "opengl"
require "glut"

vs = <<EOF
attribute vec3 position;

void main(){
    vec4 pos = gl_ModelViewProjectionMatrix * vec4(position, 1.0);

    gl_FrontColor.r = sin(4 * pos.x);
    gl_FrontColor.g = sin(4 * pos.y);
    gl_FrontColor.b = sin(4 * pos.z);

    gl_Position = pos;
}
EOF

fs = <<EOF
void main( void ) {
    gl_FragColor = gl_Color;
}
EOF

GLUT.InitWindowPosition(100, 100)
GLUT.InitWindowSize(300,300)
GLUT.Init
GLUT.InitDisplayMode(GLUT::GLUT_DOUBLE | GLUT::GLUT_RGB | GLUT::GLUT_DEPTH)
GLUT.CreateWindow("Ruby de GLSL")

program = GL.CreateProgram
for src in [{:code=>vs, :type=>GL_VERTEX_SHADER},
            {:code=>fs, :type=>GL_FRAGMENT_SHADER}]
    shader = GL.CreateShader(src[:type])
    GL.ShaderSource(shader, src[:code])
    GL.CompileShader(shader)
    GL.AttachShader(program, shader)
    GL.DeleteShader(shader)
end
GL.LinkProgram(program)
GL.UseProgram(program)

vertices = proc{
    radius=1
    tube=0.5
    segV=50
    segH=100
    vec = []
    for v in 0..segV do
        vTheta = 2 * Math::PI * v / segV
        r = Math::cos(vTheta) * tube
        y = Math::sin(vTheta) * tube
        for h in    0..segH do
            hTheta = 2 * Math::PI * h / segH
            x = Math::cos(hTheta) * (radius + r)
            z = Math::sin(hTheta) * (radius + r)
            vec << [x, y, z]
        end
    end
    vec.flatten
}[]

buffers = GL.GenBuffers(1)
GL.BindBuffer(GL_ARRAY_BUFFER, buffers[0])
GL.BufferData(GL_ARRAY_BUFFER, 4*vertices.size, vertices.pack('f*'), GL_STATIC_DRAW)
location = GL.GetAttribLocation(program, "position")
GL.EnableVertexAttribArray(location)
GL.VertexAttribPointer(location, 3, GL_FLOAT, false, 0, 0)

GLUT.ReshapeFunc proc{|w,h|
    GL.Viewport(0,0,w,h)
    GL.MatrixMode(GL_PROJECTION)
    GL.LoadIdentity()
    GLU.Perspective(45.0, w.to_f() / h.to_f(), 0.1, 100.0)
}

GLUT.DisplayFunc proc{
    GL.ClearColor(0, 0, 0, 1)
    GL.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    GL.DrawArrays(GL_POINTS, 0, vertices.size/3)
    GLUT.SwapBuffers
}

i = 0
update = proc {
    GLUT.TimerFunc(1000 / 30 , update , 0)
    GL.MatrixMode(GL_MODELVIEW)
    GL.LoadIdentity()
    GLU.LookAt(0.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
    GL.Rotate(i, 1, 0, 0)
    GLUT.PostRedisplay
    i = (i + 1) % 360
}
update[]

GLUT.MainLoop