面白いプログラムがあったので+αをしてみた。変更点はシェーダとと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