func fireParticles() *effects.ParticleSystem { img, _ := assets.ImportImageCached("TestAssets/Fire.png") fire := effects.CreateParticleSystem(effects.ParticleSettings{ MaxParticles: 12, ParticleEmitRate: 3, BaseGeometry: renderer.CreateBox(float32(1), float32(1)), TotalFrames: 36, FramesX: 6, FramesY: 6, MaxLife: 0.8, MinLife: 1.5, StartColor: color.NRGBA{255, 180, 80, 255}, EndColor: color.NRGBA{255, 60, 20, 255}, StartSize: mgl32.Vec3{1, 1, 1}.Mul(0.16), EndSize: mgl32.Vec3{1, 1, 1}.Mul(0.23), MinTranslation: mgl32.Vec3{1, 1, 1}.Mul(-0.01), MaxTranslation: mgl32.Vec3{1, 1, 1}.Mul(0.01), MinStartVelocity: mgl32.Vec3{-0.02, 0, -0.02}, MaxStartVelocity: mgl32.Vec3{0.02, 0.08, 0.02}, MinRotation: 3.0, MaxRotation: 3.6, }) fire.Node.Material = renderer.NewMaterial(renderer.NewTexture("diffuseMap", img, false)) return fire }
//imports an obj from a filePath and return a Geometry func ImportObj(filePath string) (geometry *renderer.Geometry, material *renderer.Material, err error) { obj := &objData{Indicies: make([]uint32, 0, 0), Vertices: make([]float32, 0, 0)} vertexList := make([]float32, 0, 0) uvList := make([]float32, 0, 0) normalList := make([]float32, 0, 0) //split the file name from the file path filePathTokens := strings.Split(strings.Replace(filePath, "\\", "/", -1), "/") fileName := filePathTokens[len(filePathTokens)-1] path := strings.TrimRight(filePath, fileName) //open the file and read all lines file, err := os.Open(filePath) if err != nil { fmt.Printf("Error opening geometry file: %v\n", err) return } defer file.Close() var mtlErr error scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() tokens := strings.Fields(line) if len(tokens) > 0 { dataType := tokens[0] if dataType == "o" { //sub mesh obj.Name = tokens[1] } else if dataType == "v" { //xyz vertex vertexList = append(vertexList, stf(tokens[1]), stf(tokens[2]), stf(tokens[3])) } else if dataType == "vt" { //uv coord uvList = append(uvList, stf(tokens[1]), stf(tokens[2])) } else if dataType == "vn" { //xyz vertex normal normalList = append(normalList, stf(tokens[1]), stf(tokens[2]), stf(tokens[3])) } else if dataType == "f" { // v/t/n face obj.processFace(line, vertexList, uvList, normalList) } else if dataType == "mtllib" { obj.Mtl, mtlErr = importMTL(path, tokens[1]) } else if dataType == "usemtl" { //mtl material //TODO: multiple mtls } } } geometry = renderer.CreateGeometry(obj.Indicies, obj.Vertices) if mtlErr == nil && obj.Mtl != nil { textures := []*renderer.Texture{} for key, img := range obj.Mtl.maps { textures = append(textures, renderer.NewTexture(key, img, true)) } material = renderer.NewMaterial(textures...) } if err = scanner.Err(); err != nil { fmt.Printf("Error loading geometry: %v\n", err) return } return }
func sparkParticles() *effects.ParticleSystem { img, _ := assets.ImportImageCached("TestAssets/Spark.png") smoke := effects.CreateParticleSystem(effects.ParticleSettings{ MaxParticles: 7, ParticleEmitRate: 7, BaseGeometry: renderer.CreateBox(float32(1), float32(1)), TotalFrames: 1, FramesX: 1, FramesY: 1, MaxLife: 1.0, MinLife: 0.7, StartColor: color.NRGBA{255, 220, 180, 255}, EndColor: color.NRGBA{255, 155, 55, 255}, StartSize: mgl32.Vec3{1, 1, 1}.Mul(0.008), EndSize: mgl32.Vec3{1, 1, 1}.Mul(0.005), MinTranslation: mgl32.Vec3{1, 1, 1}.Mul(-0.04), MaxTranslation: mgl32.Vec3{1, 1, 1}.Mul(0.04), MinStartVelocity: mgl32.Vec3{-0.5, 0.0, -0.5}, MaxStartVelocity: mgl32.Vec3{0.5, 1.0, 0.5}, Acceleration: mgl32.Vec3{0.0, -1.0, 0.0}, OnParticleUpdate: func(p *effects.Particle) { p.Scale[0] = p.Scale[0] * (1 + p.Velocity.Len()*3.5) p.Orientation = mgl32.QuatBetweenVectors(mgl32.Vec3{1, 0, 0}, p.Velocity) }, }) smoke.Node.Material = renderer.NewMaterial(renderer.NewTexture("diffuseMap", img, false)) return smoke }
func majicParticles() *effects.ParticleGroup { img, _ := assets.ImportImageCached("resources/majic.png") material := renderer.NewMaterial(renderer.NewTexture("diffuseMap", img, false)) particleSystem := effects.CreateParticleSystem(effects.ParticleSettings{ MaxParticles: 300, ParticleEmitRate: 700, BaseGeometry: renderer.CreateBox(float32(1), float32(1)), TotalFrames: 9, FramesX: 3, FramesY: 3, MaxLife: 1.3, MinLife: 0.7, StartColor: color.NRGBA{254, 254, 254, 254}, EndColor: color.NRGBA{254, 254, 254, 254}, StartSize: mgl32.Vec2{10, 10}.Vec3(0), EndSize: mgl32.Vec2{10, 10}.Vec3(0), MinTranslation: mgl32.Vec2{-1, -1}.Vec3(0), MaxTranslation: mgl32.Vec2{1, 1}.Vec3(0), MinStartVelocity: mgl32.Vec2{-170, -170}.Vec3(0), MaxStartVelocity: mgl32.Vec2{170, 170}.Vec3(0), MaxRotation: -3.14, MinRotation: 3.14, }) particleSystem.FaceCamera = false particleGroup := effects.NewParticleGroup(nil, particleSystem) particleGroup.Node.Material = material return particleGroup }
func sparkParticles() *effects.ParticleGroup { img, _ := assets.ImportImageCached("resources/spark.png") material := renderer.NewMaterial(renderer.NewTexture("diffuseMap", img, false)) particleSystem := effects.CreateParticleSystem(effects.ParticleSettings{ MaxParticles: 80, ParticleEmitRate: 400, BaseGeometry: renderer.CreateBox(float32(1), float32(1)), TotalFrames: 1, FramesX: 1, FramesY: 1, MaxLife: 3.3, MinLife: 1.7, StartColor: color.NRGBA{254, 160, 90, 254}, EndColor: color.NRGBA{254, 160, 90, 254}, StartSize: mgl32.Vec2{2, 2}.Vec3(0), EndSize: mgl32.Vec2{2, 2}.Vec3(0), MinTranslation: mgl32.Vec2{-5, -5}.Vec3(0), MaxTranslation: mgl32.Vec2{5, 5}.Vec3(0), MinStartVelocity: mgl32.Vec2{-100, -100}.Vec3(0), MaxStartVelocity: mgl32.Vec2{100, 100}.Vec3(0), Acceleration: mgl32.Vec2{0, 400}.Vec3(0), OnParticleUpdate: func(p *effects.Particle) { p.Scale[0] = p.Scale[0] * (1 + p.Velocity.Len()*0.05) p.Orientation = mgl32.QuatBetweenVectors(mgl32.Vec3{1, 0, 0}, p.Velocity) }, }) particleSystem.FaceCamera = false particleGroup := effects.NewParticleGroup(nil, particleSystem) particleGroup.Node.Material = material return particleGroup }
func dustParticles() *effects.ParticleGroup { img, _ := assets.ImportImageCached("resources/smoke.png") material := renderer.NewMaterial(renderer.NewTexture("diffuseMap", img, false)) particleSystem := effects.CreateParticleSystem(effects.ParticleSettings{ MaxParticles: 5, ParticleEmitRate: 20, BaseGeometry: renderer.CreateBox(float32(1), float32(1)), TotalFrames: 64, FramesX: 8, FramesY: 8, MaxLife: 3.3, MinLife: 2.7, StartColor: color.NRGBA{254, 254, 254, 120}, EndColor: color.NRGBA{254, 254, 254, 0}, StartSize: mgl32.Vec2{40, 40}.Vec3(0), EndSize: mgl32.Vec2{180, 180}.Vec3(0), MinTranslation: mgl32.Vec2{-2, -2}.Vec3(0), MaxTranslation: mgl32.Vec2{2, 2}.Vec3(0), MinStartVelocity: mgl32.Vec2{-5.0, -5.0}.Vec3(0), MaxStartVelocity: mgl32.Vec2{5.0, 5.0}.Vec3(0), MaxRotation: -3.14, MinRotation: 3.14, }) particleSystem.FaceCamera = false particleGroup := effects.NewParticleGroup(nil, particleSystem) particleGroup.Node.Material = material return particleGroup }
func (e *Editor) initSelectSprite() { img, _ := assets.DecodeImage(bytes.NewBuffer(util.Base64ToBytes(GeometryIconData))) mat := renderer.NewMaterial(renderer.NewTexture("diffuseMap", img, false)) selectSprite := effects.CreateSprite(1, 1, 1, mat) spriteNode := renderer.NewNode() spriteNode.RendererParams = &renderer.RendererParams{Unlit: true} spriteNode.Add(selectSprite) e.selectSprite = selectSprite e.gameEngine.AddSpatialTransparent(spriteNode) }
func NewCharacter() *Character { characterImg, _ := assets.ImportImageCached("resources/stickman.png") characterMat := renderer.NewMaterial(renderer.NewTexture("diffuseMap", characterImg, false)) sprite := effects.CreateSprite(4, 4, 1, characterMat) sprite.FaceCamera = false sprite.SetScale(mgl32.Vec2{characterSize, characterSize}.Vec3(0)) sprite.SetTranslation(mgl32.Vec2{400, 400}.Vec3(0)) body := chipmunkPhysics.NewChipmunkBody(1, 1) circle := chipmunk.NewCircle(vect.Vector_Zero, float32(characterSize*0.5)) body.Body.AddShape(circle) return &Character{ body: body, sprite: sprite, } }
func (ie *ImageElement) SetImage(img image.Image) { mat := renderer.NewMaterial(renderer.NewTexture("diffuseMap", img, false)) ie.node.Material = mat ie.img = img }
func setupScene(gameEngine engine.Engine, shader *renderer.Shader) { camera := gameEngine.Camera() transparentNode := renderer.NewNode() gameEngine.AddSpatialTransparent(transparentNode) transparentNode.RendererParams = &renderer.RendererParams{ DepthTest: true, Unlit: true, Transparency: renderer.EMISSIVE, } // Sky cubemap skyImg, err := assets.ImportImage("TestAssets/cloudSky.jpg") if err == nil { skyImg = imaging.AdjustBrightness(skyImg, -30) skyImg = imaging.AdjustContrast(skyImg, 30) geom := renderer.CreateSkyBox() geom.Transform(mgl32.Scale3D(10000, 10000, 10000)) skyNode := renderer.NewNode() skyNode.SetOrientation(mgl32.QuatRotate(1.57, mgl32.Vec3{0, 1, 0})) skyNode.Material = renderer.NewMaterial(renderer.NewTexture("diffuseMap", skyImg, false)) skyNode.RendererParams = renderer.NewRendererParams() skyNode.RendererParams.CullBackface = false skyNode.RendererParams.Unlit = true skyNode.Add(geom) gameEngine.AddSpatial(skyNode) // create an environmentMap using the skybox texture envCubeMap := renderer.NewCubemap("environmentMap", skyImg, true) gameEngine.DefaultCubeMap(envCubeMap) } // load scene objs objs := []string{ "TestAssets/wellScene/floor.obj", "TestAssets/wellScene/frame1.obj", "TestAssets/wellScene/frame2.obj", "TestAssets/wellScene/well.obj", "TestAssets/wellScene/torches.obj", } for _, objFile := range objs { if geom, mat, err := assets.ImportObjCached(objFile); err == nil { sceneNode := renderer.NewNode() sceneNode.Add(geom) sceneNode.Material = mat sceneNode.RendererParams = renderer.NewRendererParams() sceneNode.RendererParams.CullBackface = false gameEngine.AddSpatial(sceneNode) } } for i := 0; i < 2; i++ { torchLocation := mgl32.Vec3{0.86, 1.76, 1.05} if i == 1 { torchLocation = mgl32.Vec3{0.86, 1.76, -1.05} } fire := fireParticles() spark := sparkParticles() torchParticles := effects.NewParticleGroup(camera, fire, spark) torchParticles.SetTranslation(torchLocation) transparentNode.Add(torchParticles) gameEngine.AddUpdatable(torchParticles) light := renderer.NewLight(renderer.POINT) light.SetTranslation(torchLocation.Add(mgl32.Vec3{0, 0.05, 0})) gameEngine.AddLight(light) var x float64 gameEngine.AddUpdatable(engine.UpdatableFunc(func(dt float64) { x += dt mag := float32(math.Abs(0.6*math.Sin(3*x)+0.3*math.Sin(4*x)+0.15*math.Sin(7*x)+0.1*math.Sin(15*x))) + 0.5 mag *= 0.05 light.Color = [3]float32{1 * mag, 0.6 * mag, 0.4 * mag} })) } }
func (c *Container) SetBackgroundImage(img image.Image) { mat := renderer.NewMaterial(renderer.NewTexture("diffuseMap", img, false)) c.background.Material = mat }
func (e *Editor) Start() { glRenderer := opengl.NewOpenglRenderer("GoEngine Editor", 1800, 900, false) e.renderer = glRenderer e.gameEngine = engine.NewEngine(e.renderer) e.gameEngine.Start(func() { shader, err := assets.ImportShader( filepath.Join(e.assetDir, "shaders/build/pbr.vert"), filepath.Join(e.assetDir, "shaders/build/pbr.frag"), ) if err != nil { panic("error importing shader") } e.gameEngine.DefaultShader(shader) // Sky cubemap skyImg, err := assets.ImportImage(filepath.Join(e.assetDir, "resources/cubemap.png")) if err == nil { geom := renderer.CreateSkyBox() geom.Transform(mgl32.Scale3D(10000, 10000, 10000)) skyNode := renderer.NewNode() skyNode.SetOrientation(mgl32.QuatRotate(1.57, mgl32.Vec3{0, 1, 0})) skyNode.Material = renderer.NewMaterial(renderer.NewTexture("diffuseMap", skyImg, false)) skyNode.RendererParams = renderer.NewRendererParams() skyNode.RendererParams.CullBackface = false skyNode.RendererParams.Unlit = true skyNode.Add(geom) e.gameEngine.AddSpatial(skyNode) // create an environmentMap using the skybox texture envCubeMap := renderer.NewCubemap("environmentMap", skyImg, true) e.gameEngine.DefaultCubeMap(envCubeMap) } l := renderer.NewLight(renderer.DIRECTIONAL) l.Color = [3]float32{0.7, 0.7, 0.8} e.gameEngine.AddLight(l) //root node e.gameEngine.AddSpatial(e.rootMapNode) //input/controller manager e.controllerManager = glfwController.NewControllerManager(glRenderer.Window) //camera + player camera := e.gameEngine.Camera() freeMoveActor := actor.NewFreeMoveActor(camera) freeMoveActor.MoveSpeed = 20.0 freeMoveActor.LookSpeed = 0.002 mainController := controller.NewBasicMovementController(freeMoveActor, true) e.controllerManager.AddController(mainController.(glfwController.Controller)) e.gameEngine.AddUpdatable(freeMoveActor) e.initSelectSprite() e.gameEngine.AddUpdatable(engine.UpdatableFunc(e.updateSelectSprite)) //editor controller e.controllerManager.AddController(NewEditorController(e).(glfwController.Controller)) //custom controller e.customController = controller.CreateController() e.controllerManager.AddController(e.customController.(glfwController.Controller)) e.setupUI() }) }
func main() { glRenderer := opengl.NewOpenglRenderer("Simple", 800, 800, false) gameEngine := engine.NewEngine(glRenderer) gameEngine.InitFpsDial() gameEngine.Start(func() { if shader, err := assets.ImportShader("shaders/build/basic.vert", "shaders/build/basic.frag"); err == nil { gameEngine.DefaultShader(shader) } // sky cube skyImg, err := assets.ImportImage("resources/cubemap.png") if err == nil { geom := renderer.CreateSkyBox() geom.Transform(mgl32.Scale3D(10000, 10000, 10000)) skyNode := renderer.NewNode() skyNode.SetOrientation(mgl32.QuatRotate(1.57, mgl32.Vec3{0, 1, 0})) skyNode.Material = renderer.NewMaterial(renderer.NewTexture("diffuseMap", skyImg, false)) skyNode.RendererParams = renderer.NewRendererParams() skyNode.RendererParams.CullBackface = false skyNode.RendererParams.Unlit = true skyNode.Add(geom) gameEngine.AddSpatial(skyNode) } // Add some light to the scene ambientLight := renderer.NewLight(renderer.AMBIENT) ambientLight.Color = [3]float32{0.3, 0.3, 0.3} gameEngine.AddLight(ambientLight) // Create a red box geometry, attach to a node, add the node to the scenegraph boxGeometry := renderer.CreateBox(10, 10) boxGeometry.SetColor(color.NRGBA{254, 0, 0, 254}) boxNode := renderer.NewNode() boxNode.RendererParams = renderer.NewRendererParams() boxNode.RendererParams.CullBackface = false boxNode.Material = renderer.NewMaterial() boxNode.SetTranslation(mgl32.Vec3{30, 0}) boxNode.Add(boxGeometry) gameEngine.AddSpatial(boxNode) // make the box spin var angle float64 gameEngine.AddUpdatable(engine.UpdatableFunc(func(dt float64) { angle += dt q := mgl32.QuatRotate(float32(angle), mgl32.Vec3{0, 1, 0}) boxNode.SetOrientation(q) })) // input/controller manager controllerManager := glfwController.NewControllerManager(glRenderer.Window) // camera + wasd controls camera := gameEngine.Camera() freeMoveActor := actor.NewFreeMoveActor(camera) freeMoveActor.Location = mgl32.Vec3{} mainController := controller.NewBasicMovementController(freeMoveActor, false) controllerManager.AddController(mainController.(glfwController.Controller)) gameEngine.AddUpdatable(freeMoveActor) //lock the cursor glRenderer.LockCursor(true) // custom key bindings customController := controller.CreateController() controllerManager.AddController(customController.(glfwController.Controller)) // close window and exit on escape customController.BindKeyAction(func() { glRenderer.Window.SetShouldClose(true) }, controller.KeyEscape, controller.Press) }) }