func (p *ShaderProgram) Link() (uint32, error) { defer func() { for _, shaders := range p.shaders { for _, shader := range shaders { gl.DeleteShader(shader) } } *p = ShaderProgram{} }() program := gl.CreateProgram() for _, shaders := range p.shaders { for _, shader := range shaders { gl.AttachShader(program, shader) } } gl.LinkProgram(program) var status int32 gl.GetProgramiv(program, gl.LINK_STATUS, &status) if status == gl.FALSE { var logLength int32 gl.GetProgramiv(program, gl.INFO_LOG_LENGTH, &logLength) log := strings.Repeat("\x00", int(logLength+1)) gl.GetProgramInfoLog(program, logLength, nil, gl.Str(log)) return 0, fmt.Errorf("failed to link program:\n%s", log) } return program, nil }
func (p *ShaderProgram) AddShader(source string, kind ShaderKind) error { shader := gl.CreateShader(uint32(kind)) csource := gl.Str(source + "\x00") gl.ShaderSource(shader, 1, &csource, nil) gl.CompileShader(shader) var status int32 gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status) if status == gl.FALSE { var logLength int32 gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &logLength) log := strings.Repeat("\x00", int(logLength+1)) gl.GetShaderInfoLog(shader, logLength, nil, gl.Str(log)) return fmt.Errorf("failed to compile %v shader:\n%s", kindString(kind), log) } p.shaders[kind] = append(p.shaders[kind], shader) return nil }
func (s *MainState) Render() error { gl.UseProgram(s.program) gl.UniformMatrix4fv(s.projectionUniform, 1, false, &s.projection[0]) /* gl.BindVertexArray(s.vao) gl.BindBuffer(gl.ARRAY_BUFFER, s.vbo) */ gl.BufferData( gl.ARRAY_BUFFER, int(PARTICLE_COUNT_DEFAULT*unsafe.Sizeof([2]float32{})), nil, gl.STREAM_DRAW) data, err := sliceMap2Float32Buffer(gl.WRITE_ONLY, PARTICLE_COUNT_DEFAULT) if err != nil { return err } for i := range data { p := &s.space.Particles[i] if p == nil { return fmt.Errorf("no particle of id %d", i) } data[i][0] = float32(p.Position.X) data[i][1] = float32(p.Position.Y) } gl.UnmapBuffer(gl.ARRAY_BUFFER) data = nil positionAttrib := uint32(gl.GetAttribLocation(s.program, gl.Str("position\x00"))) gl.EnableVertexAttribArray(positionAttrib) gl.VertexAttribPointer(positionAttrib, 2, gl.FLOAT, false, 0, gl.PtrOffset(0)) gl.ClearColor(0, 0, 0, 1) gl.Clear(gl.COLOR_BUFFER_BIT) gl.DrawArrays(gl.POINTS, 0, PARTICLE_COUNT_DEFAULT) return nil }
func (s *MainState) Render() error { program := s.program gl.UseProgram(program) projectionUniform := gl.GetUniformLocation(program, gl.Str("projection\x00")) gl.UniformMatrix4fv(projectionUniform, 1, false, &projection[0]) gl.Flush() buffer := s.vertexBuffer gl.BindBuffer(gl.ARRAY_BUFFER, buffer) gl.BufferData( gl.ARRAY_BUFFER, int(PARTICLE_COUNT_DEFAULT*unsafe.Sizeof([2]float32{})), nil, gl.STREAM_DRAW) dataPointer := gl.MapBuffer(gl.ARRAY_BUFFER, gl.WRITE_ONLY) if dataPointer == nil { return fmt.Errorf("buffer data pointer is nil") } data := (*[PARTICLE_COUNT_DEFAULT][2]float32)(dataPointer) gl.ClearColor(0, 0, 0, 1) gl.Clear(gl.COLOR_BUFFER_BIT) for i := range data { p := s.space.Particle(i) if p == nil { return fmt.Errorf("no particle of id %d", i) } data[i][0] = float32(p.Position.X) data[i][1] = float32(p.Position.Y) } gl.UnmapBuffer(gl.ARRAY_BUFFER) gl.DrawArrays(gl.POINTS, 0, PARTICLE_COUNT_DEFAULT) return nil }
func (s *MainState) Init(e *engine.E) error { // Init Glow if err := gl.Init(); err != nil { return err } // Enable debug output if glfw3.ExtensionSupported("GL_ARB_debug_output") { gl.Enable(gl.DEBUG_OUTPUT_SYNCHRONOUS_ARB) gl.DebugMessageCallbackARB(gl.DebugProc(glDebugCallback), nil) } // Init shaders shaderProg := engine.NewShaderProgram() if err := shaderProg.ReadShaderFile("vert.glsl", engine.VertexShader); err != nil { return err } if err := shaderProg.ReadShaderFile("geom.glsl", engine.GeometryShader); err != nil { return err } if err := shaderProg.ReadShaderFile("frag.glsl", engine.FragmentShader); err != nil { return err } program, err := shaderProg.Link() if err != nil { return err } s.program = program gl.UseProgram(program) // Manage GL features gl.Disable(gl.DEPTH_TEST) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.Enable(gl.MULTISAMPLE) gl.Enable(gl.POLYGON_SMOOTH) gl.Enable(gl.PROGRAM_POINT_SIZE) // Init VAO gl.GenVertexArrays(1, &s.vao) gl.BindVertexArray(s.vao) e.Defer(func() { gl.DeleteVertexArrays(1, &s.vao) }) s.projectionUniform = gl.GetUniformLocation(program, gl.Str("projection\x00")) // Init VBO gl.GenBuffers(1, &s.vbo) gl.BindBuffer(gl.ARRAY_BUFFER, s.vbo) e.Defer(func() { gl.DeleteBuffers(1, &s.vbo) }) positionAttrib := uint32(gl.GetAttribLocation(program, gl.Str("position\x00"))) gl.EnableVertexAttribArray(positionAttrib) gl.VertexAttribPointer(positionAttrib, 2, gl.FLOAT, false, 0, gl.PtrOffset(0)) // Init space space, err := gputicles.New() if err != nil { return err } s.space = space /* for i := 0; i < PARTICLE_COUNT_DEFAULT; i++ { particle := space.MkParticle(PARTICLE_MASS_DEFAULT) particle.Position = randVect() //particle.Velocity = randVect().Div(8) } */ for i := 0; i < PARTICLE_COUNT_DEFAULT/2; i++ { particle := space.MkParticle(PARTICLE_MASS_DEFAULT) particle.Position = randVect().Div(2).Add(vect.V{-0.5, -0.5}) } for i := PARTICLE_COUNT_DEFAULT / 2; i < PARTICLE_COUNT_DEFAULT; i++ { particle := space.MkParticle(PARTICLE_MASS_DEFAULT) particle.Position = randVect().Div(2).Add(vect.V{0.5, 0.5}) } return nil }
func (s *MainState) Init(eng *engine.E) error { println("initializing state") // Init Glow if err := gl.Init(); err != nil { return err } // Enable debug output if glfw3.ExtensionSupported("GL_ARB_debug_output") { gl.Enable(gl.DEBUG_OUTPUT_SYNCHRONOUS_ARB) gl.DebugMessageCallbackARB(gl.DebugProc(glDebugCallback), nil) } shaderProg := engine.NewShaderProgram() if err := shaderProg.ReadShaderFile("vert.glsl", engine.VertexShader); err != nil { return err } if err := shaderProg.ReadShaderFile("geom.glsl", engine.GeometryShader); err != nil { return err } if err := shaderProg.ReadShaderFile("frag.glsl", engine.FragmentShader); err != nil { return err } program, err := shaderProg.Link() if err != nil { return err } s.program = program gl.UseProgram(program) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) //gl.Enable(gl.DITHER) gl.Enable(gl.MULTISAMPLE) gl.Enable(gl.POLYGON_SMOOTH) gl.Enable(gl.PROGRAM_POINT_SIZE) // Init VAO var vao uint32 gl.GenVertexArrays(1, &vao) gl.BindVertexArray(vao) s.vertexArray = vao eng.Defer(func() { gl.DeleteVertexArrays(1, &vao) }) // Set projection projectionUniform := gl.GetUniformLocation(program, gl.Str("projection\x00")) gl.UniformMatrix4fv(projectionUniform, 1, false, &projection[0]) // Initialize vertex buffer var buffer uint32 gl.GenBuffers(1, &buffer) gl.BindBuffer(gl.ARRAY_BUFFER, buffer) s.vertexBuffer = buffer eng.Defer(func() { gl.DeleteBuffers(1, &buffer) }) positionAttrib := uint32(gl.GetAttribLocation(program, gl.Str("position\x00"))) gl.EnableVertexAttribArray(positionAttrib) gl.VertexAttribPointer(positionAttrib, 2, gl.FLOAT, false, 0, gl.PtrOffset(0)) // Initialize space space := leapfrog.New() for i := 0; i < PARTICLE_COUNT_DEFAULT; i++ { particle := space.MkParticle(PARTICLE_MASS_DEFAULT) particle.Position = randVect().Div(2) } s.space = space // Deinit is not part of interface, but can be deferred manually: eng.Defer(s.Deinit) return nil }