// Creates a new Framebuffer. func NewFramebuffer(w int, h int) (fb *Framebuffer, err error) { var ( buffer gl.Framebuffer texture gl.Texture ) buffer = gl.GenFramebuffer() buffer.Bind() texture = gl.GenTexture() texture.Bind(gl.TEXTURE_2D) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, nil) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0) gl.DrawBuffer(gl.COLOR_ATTACHMENT0) if gl.CheckFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE { err = fmt.Errorf("Framebuffer could not be set up") return } fb = &Framebuffer{ Buffer: buffer, Texture: texture, Width: w, Height: h, } return }
// Commit creates the actual texture from the atlas image data. // This should be called after all regions have been defined and set, // and before you start using the texture for display. func (a *TextureAtlas) Commit(target gl.GLenum) { gl.PushAttrib(gl.CURRENT_BIT | gl.ENABLE_BIT) gl.Enable(target) a.texture.Bind(target) gl.TexParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.TexParameteri(target, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR) switch a.depth { case 4: gl.TexImage2D(target, 0, gl.RGBA, a.width, a.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, a.data) case 3: gl.TexImage2D(target, 0, gl.RGB, a.width, a.height, 0, gl.RGB, gl.UNSIGNED_BYTE, a.data) case 1: gl.TexImage2D(target, 0, gl.ALPHA, a.width, a.height, 0, gl.ALPHA, gl.UNSIGNED_BYTE, a.data) } gl.PopAttrib() }
// loadFont loads the given font data. This does not deal with font scaling. // Scaling should be handled by the independent Bitmap/Truetype loaders. // We therefore expect the supplied image and charset to already be adjusted // to the correct font scale. // // The image should hold a sprite sheet, defining the graphical layout for // every glyph. The config describes font metadata. func loadFont(img *image.RGBA, config *FontConfig) (f *Font, err error) { f = new(Font) f.Config = config // Resize image to next power-of-two. img = glh.Pow2Image(img).(*image.RGBA) ib := img.Bounds() f.Width = ib.Dx() f.Height = ib.Dy() // Create the texture itself. It will contain all glyphs. // Individual glyph-quads display a subset of this texture. f.Texture = gl.GenTexture() f.Texture.Bind(gl.TEXTURE_2D) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, ib.Dx(), ib.Dy(), 0, gl.RGBA, gl.UNSIGNED_BYTE, img.Pix) // file, err := os.Create("font.png") // if err != nil { // log.Fatal(err) // } // err = png.Encode(file, img) // if err != nil { // log.Fatal(err) // } return }
func loadTextures() (err error) { textures = make([]gl.Texture, len(texturefiles)) ///创建文件存储空间数组 gl.GenTextures(textures) ///告诉OpenGL我们想生成一个纹理名字 for i := range texturefiles { ///告诉OpenGL将纹理名字 texture[0] 绑定到纹理目标上。 ///2D纹理只有高度(在 Y 轴上)和宽度(在 X 轴上)。主函数将纹理名字指派给纹理数据。 ///本例中我们告知OpenGL, texture[i] 处的内存已经可用。我们创建的纹理将存储在 texture[i] 的 指向的内存区域。 textures[i].Bind(gl.TEXTURE_2D) ///绑定 if !glfw.LoadTexture2D(texturefiles[i], 0) { ///加载图片 return errors.New("Failed to load texture: " + texturefiles[i]) } /* 下面的两行告诉OpenGL在显示图像时,当它比放大得原始的纹理大 ( GL_TEXTURE_MAG_FILTER ) 或缩小得比原始得纹理小( GL_TEXTURE_MIN_FILTER )时OpenGL采用的滤波方式。 通常这两种情况下我都采用 GL_LINEAR 。这使得纹理从很远处到离屏幕很近时都平滑显示。 使用 GL_LINEAR 需要CPU和显卡做更多的运算。如果您的机器很慢,您也许应该采用 GL_NEAREST 。 过滤的纹理在放大的时候,看起来斑驳的很『译者注:马赛克啦』。您也可以结合这两种滤波方式。 在近处时使用 GL_LINEAR ,远处时 GL_NEAREST 。 */ gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) ///线形滤波 gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) ///线形滤波 } return }
func (t *Texture) Options(filter, clamp int) { t.Bind() gl.TexParameteri(t.target, gl.TEXTURE_MIN_FILTER, filter) gl.TexParameteri(t.target, gl.TEXTURE_MAG_FILTER, filter) gl.TexParameteri(t.target, gl.TEXTURE_WRAP_S, clamp) gl.TexParameteri(t.target, gl.TEXTURE_WRAP_T, clamp) }
// Create a new texture, initialize it to have a `gl.LINEAR` filter and use // `gl.CLAMP_TO_EDGE`. func NewTexture(w, h int) *Texture { texture := &Texture{gl.GenTexture(), w, h} With(texture, func() { gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE) }) return texture }
func getGLTexture(img image.Image, smoothing int) (gltexture gl.Texture, err error) { var data *bytes.Buffer if data, err = encodeTGA("texture", img); err != nil { return } gltexture = gl.GenTexture() gltexture.Bind(gl.TEXTURE_2D) if !glfw.LoadMemoryTexture2D(data.Bytes(), 0) { err = fmt.Errorf("Failed to load texture") return } gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, smoothing) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, smoothing) return }
func MakeTextureFromTGA(fname string) gl.Texture { tex := gl.GenTexture() tex.Bind(gl.TEXTURE_2D) glfw.LoadTexture2D(fname, 0) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.GenerateMipmap(gl.TEXTURE_2D) // glh.OpenGLSentinel() // check for errors return tex }
func (self *OpenGLRenderer) LoadTexture(texture *render.Texture) gl.Texture { glTexture := gl.GenTexture() glTexture.Bind(gl.TEXTURE_2D) defer glTexture.Unbind(gl.TEXTURE_2D) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) self.glTexImage2D(gl.TEXTURE_2D, texture) gl.GenerateMipmap(gl.TEXTURE_2D) return glTexture }
func loadTextures() (err error) { textures = make([]gl.Texture, len(texturefiles)) gl.GenTextures(textures) for i := range texturefiles { textures[i].Bind(gl.TEXTURE_2D) if !glfw.LoadTexture2D(texturefiles[i], 0) { return errors.New("Failed to load texture: " + texturefiles[i]) } gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) } return }
func (v *Video) Render() { for running { select { case dimensions := <-v.resize: v.ResizeEvent(dimensions[0], dimensions[1]) case val := <-v.tick: slice := make([]uint8, len(val)*3) for i := 0; i < len(val); i = i + 1 { slice[i*3+0] = (uint8)((val[i] >> 16) & 0xff) slice[i*3+1] = (uint8)((val[i] >> 8) & 0xff) slice[i*3+2] = (uint8)((val[i]) & 0xff) } gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) v.tex.Bind(gl.TEXTURE_2D) if ppu.OverscanEnabled { gl.TexImage2D(gl.TEXTURE_2D, 0, 3, 240, 224, 0, gl.RGB, gl.UNSIGNED_BYTE, slice) } else { gl.TexImage2D(gl.TEXTURE_2D, 0, 3, 256, 240, 0, gl.RGB, gl.UNSIGNED_BYTE, slice) } gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.Begin(gl.QUADS) gl.TexCoord2f(0.0, 1.0) gl.Vertex3f(-1.0, -1.0, 0.0) gl.TexCoord2f(1.0, 1.0) gl.Vertex3f(1.0, -1.0, 0.0) gl.TexCoord2f(1.0, 0.0) gl.Vertex3f(1.0, 1.0, 0.0) gl.TexCoord2f(0.0, 0.0) gl.Vertex3f(-1.0, 1.0, 0.0) gl.End() if v.screen != nil { sdl.GL_SwapBuffers() } v.frametick <- true } } }
func uploadTexture_RGBA32(w, h int, data []byte) gl.Texture { id := gl.GenTexture() id.Bind(gl.TEXTURE_2D) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int(w), int(h), 0, gl.RGBA, gl.UNSIGNED_BYTE, data) if gl.GetError() != gl.NO_ERROR { id.Delete() panic("Failed to load a texture") return 0 } return id }
func loadTextures() (err error) { gl.GenTextures(textures) // Texture 1 textures[0].Bind(gl.TEXTURE_2D) if !glfw.LoadTexture2D(texturefiles[0], 0) { return errors.New("Failed to load texture: " + texturefiles[0]) } gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) // Texture 2 textures[1].Bind(gl.TEXTURE_2D) if !glfw.LoadTexture2D(texturefiles[0], 0) { return errors.New("Failed to load texture: " + texturefiles[0]) } gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) // Texture 3 textures[2].Bind(gl.TEXTURE_2D) if !glfw.LoadTexture2D(texturefiles[0], glfw.BuildMipmapsBit) { return errors.New("Failed to load texture: " + texturefiles[0]) } gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR_MIPMAP_NEAREST) return }
func (v *Video) Render(frame []byte, frame_w int, frame_h int) { gl.Clear(gl.COLOR_BUFFER_BIT) v.Texture.Bind(gl.TEXTURE_2D) gl.TexImage2D(gl.TEXTURE_2D, 0, 3, frame_w, frame_h, 0, gl.RGB, gl.UNSIGNED_BYTE, frame) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.Begin(gl.QUADS) gl.TexCoord2f(0.0, 1.0) gl.Vertex3f(-1.0, -1.0, 0.0) gl.TexCoord2f(1.0, 1.0) gl.Vertex3f(1.0, -1.0, 0.0) gl.TexCoord2f(1.0, 0.0) gl.Vertex3f(1.0, 1.0, 0.0) gl.TexCoord2f(0.0, 0.0) gl.Vertex3f(-1.0, 1.0, 0.0) gl.End() glfw.SwapBuffers() }
func (self *OpenGLRenderer) loadCubeMap(material *render.Material) gl.Texture { glTexture := gl.GenTexture() glTexture.Bind(gl.TEXTURE_CUBE_MAP) defer glTexture.Unbind(gl.TEXTURE_CUBE_MAP) gl.TexParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE) self.glTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, material.CubeMap[render.CubeFace_Right]) self.glTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, material.CubeMap[render.CubeFace_Left]) self.glTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, material.CubeMap[render.CubeFace_Top]) self.glTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, material.CubeMap[render.CubeFace_Bottom]) self.glTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, material.CubeMap[render.CubeFace_Front]) self.glTexImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, material.CubeMap[render.CubeFace_Back]) return glTexture }
// bind the given atlas to the current GL context // // the current implementation is very stupid, since it will // upload the texture every single call. // // later, improve this to upload only if there is a real need for it func (a *Atlas) bind() error { // discard any possible error if err := checkGlError(); err != nil { return err } if gl.Object(a.gltex).IsTexture() { a.gltex = gl.GenTexture() } a.gltex.Bind(gl.TEXTURE_2D) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, a.data.Bounds().Dx(), a.data.Bounds().Dy(), 0, gl.RGBA, gl.UNSIGNED_BYTE, a.data.Pix) if err := checkGlError(gl.OUT_OF_MEMORY, gl.INVALID_OPERATION); err != nil { return err } gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.GenerateMipmap(gl.TEXTURE_2D) panicGlError() return nil }
// Packs image into a texture of size * size dimensions func (i *ImagePacker) pack(size int) (SpriteSheet, error) { rootNode := newNode(size, size) for v, img := range i.images { err := rootNode.recInsert(img.w, img.h, v) if err != nil { return SpriteSheet{}, err } } nodeImage := image.NewRGBA(image.Rect(0, 0, size, size)) traverseNodes(rootNode, func(nd node) { draw.Draw(nodeImage, image.Rect(nd.rc.left, nd.rc.top, nd.rc.right, nd.rc.bottom), i.images[nd.id].image, image.ZP, draw.Src) i.sprites[nd.id].left = float32(nd.rc.left) / float32(size) i.sprites[nd.id].top = float32(nd.rc.bottom) / float32(size) i.sprites[nd.id].right = float32(nd.rc.right) / float32(size) i.sprites[nd.id].bottom = float32(nd.rc.top) / float32(size) i.sprites[nd.id].W = float32(nd.rc.right - nd.rc.left) i.sprites[nd.id].H = float32(nd.rc.bottom - nd.rc.top) }) texture := gl.GenTexture() texture.Bind(gl.TEXTURE_2D) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, nodeImage.Pix) texture.Unbind(gl.TEXTURE_2D) spriteSheet := NewSpriteSheet(texture, size, size) return spriteSheet, nil }
func LoadTexture(filename string) gl.Texture { r, err := os.Open(filename) if err != nil { fmt.Fprintf(os.Stderr, "[e] %v\n", err) return 0 } defer r.Close() img, _, err := image.Decode(r) if err != nil { fmt.Fprintf(os.Stderr, "[e] %v\n", err) return 0 } // lazy way to ensure we have the correct image format for opengl rgbaImg := image.NewNRGBA(img.Bounds()) draw.Draw(rgbaImg, img.Bounds(), img, image.ZP, draw.Src) tex := gl.GenTexture() tex.Bind(gl.TEXTURE_2D) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) // flip image: first pixel is lower left corner w, h := img.Bounds().Dx(), img.Bounds().Dy() data := make([]byte, w*h*4) lineLen := w * 4 dest := len(data) - lineLen for src := 0; src < len(rgbaImg.Pix); src += rgbaImg.Stride { copy(data[dest:dest+lineLen], rgbaImg.Pix[src:src+rgbaImg.Stride]) dest -= lineLen } gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, data) return tex }
func (video *SDLVideo) initGL() { if gl.Init() != 0 { panic(sdl.GetError()) } gl.ClearColor(0.0, 0.0, 0.0, 1.0) gl.Enable(gl.CULL_FACE) gl.Enable(gl.DEPTH_TEST) video.prog = createProgram(vertShaderSrcDef, fragShaderSrcDef) posAttrib := video.prog.GetAttribLocation("vPosition") texCoordAttr := video.prog.GetAttribLocation("vTexCoord") video.textureUni = video.prog.GetAttribLocation("texture") video.texture = gl.GenTexture() gl.ActiveTexture(gl.TEXTURE0) video.texture.Bind(gl.TEXTURE_2D) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) video.prog.Use() posAttrib.EnableArray() texCoordAttr.EnableArray() vertVBO := gl.GenBuffer() vertVBO.Bind(gl.ARRAY_BUFFER) verts := []float32{-1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0} gl.BufferData(gl.ARRAY_BUFFER, len(verts)*int(unsafe.Sizeof(verts[0])), &verts[0], gl.STATIC_DRAW) textCoorBuf := gl.GenBuffer() textCoorBuf.Bind(gl.ARRAY_BUFFER) texVerts := []float32{0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0} gl.BufferData(gl.ARRAY_BUFFER, len(texVerts)*int(unsafe.Sizeof(texVerts[0])), &texVerts[0], gl.STATIC_DRAW) posAttrib.AttribPointer(2, gl.FLOAT, false, 0, uintptr(0)) texCoordAttr.AttribPointer(2, gl.FLOAT, false, 0, uintptr(0)) }
func loadTextures() (err error) { gl.GenTextures(textures) //申请纹理处理 // Texture 1 textures[0].Bind(gl.TEXTURE_2D) //绑定将处理的纹理 if !glfw.LoadTexture2D(texturefiles[0], 0) { //加载纹理 return errors.New("Failed to load texture: " + texturefiles[0]) } /* LINEAR线性滤波的纹理贴图。这需要机器有相当高的处理能力,但它们看起来很不错。 我们接着要创建的第一种纹理使用 GL_NEAREST方式。从原理上讲,这种方式没有真正进行滤波。 它只占用很小的处理能力,看起来也很差。唯一的好处是这样我们的工程在很快和很慢的机器上都可以正常运行。 您会注意到我们在 MIN 和 MAG 时都采用了GL_NEAREST,你可以混合使用 GL_NEAREST 和 GL_LINEAR。 纹理看起来效果会好些,但我们更关心速度,所以全采用低质量贴图。MIN_FILTER在图像绘制时小于贴图的原始尺寸时采用。 MAG_FILTER在图像绘制时大于贴图的原始尺寸时采用。 */ gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) //小于原始尺寸时用NEAREST处理 gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) //大于原始尺寸时用NEAREST处理 // Texture 2 textures[1].Bind(gl.TEXTURE_2D) //绑定第二个纹理 if !glfw.LoadTexture2D(texturefiles[0], 0) { //加载纹理 return errors.New("Failed to load texture: " + texturefiles[0]) } //纹理缩放时采用的处理方式 gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) /* 当图像在屏幕上变得很小的时候,很多细节将会丢失。刚才还很不错的图案变得很难看。 当您告诉OpenGL创建一个 mipmapped的纹理后,OpenGL将尝试创建不同尺寸的高质量纹理。 当您向屏幕绘制一个 mipmapped纹理的时候,OpenGL将选择它已经创建的外观最佳的纹理(带有更多细节)来绘制,而不仅仅是缩放原先的图像(这将导致细节丢失)。 我曾经说过有办法可以绕过OpenGL对纹理宽度和高度所加的限制——64、128、256,等等。 办法就是 gluBuild2DMipmaps。据我的发现,您可以使用任意的位图来创建纹理。OpenGL将自动将它缩放到正常的大小。 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); 使用三种颜色(红,绿,蓝)来生成一个2D纹理。 TextureImage[0]->sizeX 是位图宽度,extureImage[0]->sizeY 是位图高度,GL_RGB意味着我们依次使用RGB色彩。 GL_UNSIGNED_BYTE 意味着纹理数据的单位是字节。TextureImage[0]->data指向我们创建纹理所用的位图。 */ // Texture 3 textures[2].Bind(gl.TEXTURE_2D) //绑定处理第三个纹理 if !glfw.LoadTexture2D(texturefiles[0], glfw.BuildMipmapsBit) { //加载纹理 return errors.New("Failed to load texture: " + texturefiles[0]) } //指定缩放处理方式 gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR_MIPMAP_NEAREST) //golang用这个方式自动处理gluBuild2DMipmaps? return }
// Bind binds this texture. func (t *Texture) Bind() { t.glTexture.Bind(gl.TEXTURE_2D) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, t.getWrapping(t.WrapS)) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, t.getWrapping(t.WrapT)) }
// loadFont loads the given font data. This does not deal with font scaling. // Scaling should be handled by the independent Bitmap/Truetype loaders. // We therefore expect the supplied image and charset to already be adjusted // to the correct font scale. // // The image should hold a sprite sheet, defining the graphical layout for // every glyph. The config describes font metadata. func loadFont(img *image.RGBA, config *FontConfig) (f *Font, err error) { f = new(Font) f.config = config // Resize image to next power-of-two. img = glh.Pow2Image(img).(*image.RGBA) ib := img.Bounds() // Create the texture itself. It will contain all glyphs. // Individual glyph-quads display a subset of this texture. f.texture = gl.GenTexture() f.texture.Bind(gl.TEXTURE_2D) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, ib.Dx(), ib.Dy(), 0, gl.RGBA, gl.UNSIGNED_BYTE, img.Pix) // Create display lists for each glyph. f.listbase = gl.GenLists(len(config.Glyphs)) texWidth := float32(ib.Dx()) texHeight := float32(ib.Dy()) for index, glyph := range config.Glyphs { // Update max glyph bounds. if glyph.Width > f.maxGlyphWidth { f.maxGlyphWidth = glyph.Width } if glyph.Height > f.maxGlyphHeight { f.maxGlyphHeight = glyph.Height } // Quad width/height vw := float32(glyph.Width) vh := float32(glyph.Height) // Texture coordinate offsets. tx1 := float32(glyph.X) / texWidth ty1 := float32(glyph.Y) / texHeight tx2 := (float32(glyph.X) + vw) / texWidth ty2 := (float32(glyph.Y) + vh) / texHeight // Advance width (or height if we render top-to-bottom) adv := float32(glyph.Advance) gl.NewList(f.listbase+uint(index), gl.COMPILE) { gl.Begin(gl.QUADS) { gl.TexCoord2f(tx1, ty2) gl.Vertex2f(0, 0) gl.TexCoord2f(tx2, ty2) gl.Vertex2f(vw, 0) gl.TexCoord2f(tx2, ty1) gl.Vertex2f(vw, vh) gl.TexCoord2f(tx1, ty1) gl.Vertex2f(0, vh) } gl.End() switch config.Dir { case LeftToRight: gl.Translatef(adv, 0, 0) case RightToLeft: gl.Translatef(-adv, 0, 0) case TopToBottom: gl.Translatef(0, -adv, 0) } } gl.EndList() } err = glh.CheckGLError() return }
func (t *Texture) SetWraping(wrapType WrapType, wrap Wrap) { t.Bind() gl.TexParameteri(t.target, gl.GLenum(wrapType), int(wrap)) }
func (t *Texture) Param(filter, value int) { t.Bind() gl.TexParameteri(t.target, gl.GLenum(filter), value) }
func main() { b, _ := ioutil.ReadFile("./roboto/roboto-light.ttf") font, ferr := tt.Parse(b) if ferr != nil { fmt.Println("can't parse font %v , len %v", ferr.Error(), len(b)) } fc := ft.NewContext() fc.SetFont(font) glfw.SetErrorCallback(errorCallback) if !glfw.Init() { panic("Can't init glfw!") } defer glfw.Terminate() window, err := glfw.CreateWindow(800, 600, "Testing", nil, nil) if err != nil { panic(err) } window.MakeContextCurrent() gl.Init() program := gl.CreateProgram() vertexShader := gl.CreateShader(gl.VERTEX_SHADER) vertexShader.Source(` attribute vec4 a_position; attribute vec2 a_coord; varying vec2 v_coord; void main() { gl_Position = a_position; v_coord = a_coord; } `) vertexShader.Compile() fmt.Printf("vertex: %v\n", vertexShader.GetInfoLog()) fragmentShader := gl.CreateShader(gl.FRAGMENT_SHADER) fragmentShader.Source(` varying vec2 v_coord; uniform sampler2D s_picture; uniform vec4 color; uniform bool has_picture; void main() { if(has_picture) { gl_FragColor = texture2D(s_picture, v_coord); } else { gl_FragColor = color; } } `) fragmentShader.Compile() fmt.Printf("fragment %v \n", fragmentShader.GetInfoLog()) program.AttachShader(vertexShader) program.AttachShader(fragmentShader) program.Link() // ini //gl.MatrixMode(gl.PROJECTION) //gl.Ortho(0, 640, 0, 480, 0, 1) gl.ClearColor(0.5, 0.5, 0.5, 0.0) root := widget.Widget{ Name: "Red", Rect: image.Rect(0, 0, 800, 600), Background: color.RGBA{255, 128, 128, 126}, OnClick: widget.ClickInner, OnDrag: widget.DragInner, OnHover: widget.HoverInner, OnResize: widget.ResizeItself, } blue := root.AddWidget(&widget.Widget{ Name: "Blue", Rect: image.Rect(100, 100, 200, 200), Image: LoadImage("./test.png"), Background: color.RGBA{128, 128, 255, 126}, OnClick: func(w *widget.Widget, p image.Point) { root.SetTop(w) fmt.Println("Clicked blue box") widget.ClickInner(w, p) }, OnDrag: func(w *widget.Widget, p image.Point, d image.Point) bool { widget.DragInner(w, p, d) widget.DragItself(w, p, d) return true }, OnResize: widget.ResizeItself, }) blue.AddWidget(&widget.Widget{ Name: "White", Rect: image.Rect(90, 90, 100, 100), Background: color.RGBA{250, 250, 250, 250}, OnDrag: func(w *widget.Widget, p image.Point, d image.Point) bool { widget.DragItself(w, p, d) blue.Resize(d) return true }, }) root.AddWidget(&widget.Widget{ Name: "Green", Rect: image.Rect(100, 300, 200, 400), Background: color.RGBA{128, 255, 128, 126}, OnClick: func(w *widget.Widget, p image.Point) { root.SetTop(w) w.Image = LoadImage("./test2.png") }, OnDrag: widget.DragItself, }) root.AddWidget(&widget.Widget{ Name: "Black", Rect: image.Rect(100, 400, 150, 450), Background: color.RGBA{0, 0, 0, 126}, OnHover: func(w *widget.Widget, p0 image.Point, p1 image.Point) { if p1.In(w.Rect) { w.Background = color.RGBA{255, 255, 255, 126} } else { w.Background = color.RGBA{0, 0, 0, 126} } }, }) white := root.AddWidget(&widget.Widget{ Name: "White", Text: "Меня зовут Светлана, я из города Иваново. «Единая Россия» очень много сделала достижений: они подняли экономик… экономику, мы стали более лучшие… одеваться, и не было того что щас — это очень большие достижения! В сельском хозяйстве очень хорошо. (Гладин: Что именно в сельском хозяйстве они сделали?) Стало больше… земель за-а… много, ну… я не знаю даже как сказать… засеивать больше земель… а-а-а вот, овощи там, рожь — вот это всё. Что еще сказать… Так как у нас страна многонациональная, у нас в Москве очень много людей, которые очень помогают нам… с других городов… (вопрос Гладина: Вы считаете это достижение «Единой России»?) Да, это большое достижение! Очень хорошее даже! Видите ну… да… Видите ну у нас в Иванове очень хорошая стала медицина… а…что ещё… благоустройство в городах хорошее… с жильём… никаких проблем. Люди подмогают очень хорошо", Rect: image.Rect(400, 200, 700, 500), Foreground: color.RGBA{0, 0, 0, 0}, Background: color.RGBA{255, 255, 255, 126}, OnDrag: func(w *widget.Widget, p image.Point, d image.Point) bool { root.SetTop(w) widget.DragInner(w, p, d) widget.DragItself(w, p, d) return true }, OnResize: widget.ResizeItself, Padding: image.Rect(20, 20, 20, 20), }) white.AddWidget(&widget.Widget{ Name: "White", Rect: image.Rect(290, 290, 300, 300), Background: color.RGBA{0, 0, 0, 250}, OnDrag: func(w *widget.Widget, p image.Point, d image.Point) bool { widget.DragItself(w, p, d) white.Resize(d) return true }, }) x0 := 0.0 y0 := 0.0 window.SetMouseButtonCallback(func(w *glfw.Window, but glfw.MouseButton, act glfw.Action, key glfw.ModifierKey) { xpos, ypos := w.GetCursorPosition() if act == glfw.Press { root.Click(image.Point{X: int(xpos), Y: int(ypos)}) x0, y0 = xpos, ypos } }) window.SetCursorPositionCallback(func(w *glfw.Window, xpos float64, ypos float64) { root.Hover(image.Point{X: int(x0), Y: int(y0)}, image.Point{X: int(xpos), Y: int(ypos)}) if w.GetMouseButton(glfw.MouseButtonLeft) == glfw.Press { root.Drag(image.Point{X: int(x0), Y: int(y0)}, image.Point{X: int(xpos - x0), Y: int(ypos - y0)}) x0, y0 = xpos, ypos } x0, y0 = xpos, ypos }) width0, height0 := window.GetSize() window.SetSizeCallback(func(w *glfw.Window, width int, height int) { gl.Viewport(0, 0, width, height) root.Rect.Max = image.Point{width, height} width0, height0 = width, height }) /*switch(color_type){ case PNG_COLOR_TYPE_GRAY: return GL_LUMINANCE; case PNG_COLOR_TYPE_GRAY_ALPHA: return GL_LUMINANCE_ALPHA; case PNG_COLOR_TYPE_RGB: return GL_RGB; case PNG_COLOR_TYPE_RGB_ALPHA: return GL_RGBA; */ /* here init texture pool texturePool := make([widget.Widget]texture) */ for !window.ShouldClose() { //Do OpenGL stuff program.Use() gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) root.DrawBy(image.Point{}, func(w *widget.Widget, corner image.Point) { var texture gl.Texture if w.Image != nil { texture = gl.GenTexture() texture.Bind(gl.TEXTURE_2D) gl.ActiveTexture(gl.TEXTURE0) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w.Image.Rect.Dx(), w.Image.Rect.Dy(), 0, gl.RGBA, gl.UNSIGNED_BYTE, w.Image.Pix) } leftX := 2.0*float32(corner.X+w.Rect.Min.X)/float32(root.Rect.Dx()) - 1.0 leftY := 1.0 - 2.0*float32(corner.Y+w.Rect.Min.Y)/float32(root.Rect.Dy()) rightX := 2.0*float32(corner.X+w.Rect.Min.X)/float32(root.Rect.Dx()) - 1.0 rightY := 1.0 - 2.0*float32(corner.Y+w.Rect.Max.Y)/float32(root.Rect.Dy()) bottomX := 2.0*float32(corner.X+w.Rect.Max.X)/float32(root.Rect.Dx()) - 1.0 bottomY := 1.0 - 2.0*float32(corner.Y+w.Rect.Min.Y)/float32(root.Rect.Dy()) topX := 2.0*float32(corner.X+w.Rect.Max.X)/float32(root.Rect.Dx()) - 1.0 topY := 1.0 - 2.0*float32(corner.Y+w.Rect.Max.Y)/float32(root.Rect.Dy()) vertices := []float32{ leftX, leftY, rightX, rightY, bottomX, bottomY, topX, topY, } texturePoints := []float32{ 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, } s_picture := program.GetUniformLocation("s_picture") s_picture.Uniform1i(0) has_picture := program.GetUniformLocation("has_picture") if w.Image != nil { has_picture.Uniform1i(1) } else { has_picture.Uniform1i(0) } col := program.GetUniformLocation("color") r, g, b, a := w.Background.RGBA() col.Uniform4f(float32(r)/float32(0xFFFF), float32(g)/float32(0xFFFF), float32(b)/float32(0xFFFF), float32(a)/float32(0xFFFF)) gl.PixelStorei(gl.UNPACK_ALIGNMENT, gl.UNSIGNED_BYTE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) a_position := program.GetAttribLocation("a_position") a_position.AttribPointer(2, gl.FLOAT, false, 0, vertices) a_position.EnableArray() a_coord := program.GetAttribLocation("a_coord") a_coord.AttribPointer(2, gl.FLOAT, false, 0, texturePoints) a_coord.EnableArray() gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) gl.Flush() texture.Delete() if len(w.Text) > 0 { rct := w.Rect rct.Max = rct.Max.Sub(w.Rect.Min) rct.Min = rct.Min.Sub(w.Rect.Min) fg := image.NewRGBA(rct) fgu := image.NewUniform(color.RGBA{0, 16, 32, 255}) draw.Draw(fg, fg.Bounds(), fgu, image.ZP, draw.Src) bg := image.NewRGBA(rct) bgu := image.NewUniform(color.RGBA{255, 255, 255, 255}) draw.Draw(bg, bg.Bounds(), bgu, image.ZP, draw.Src) lineHeight := 20.0 fc.SetDPI(100.0) fc.SetFont(font) fc.SetFontSize(12.0) fc.SetClip(bg.Bounds()) fc.SetDst(bg) fc.SetSrc(fg) p0 := ft.Pt(w.Padding.Min.X, w.Padding.Min.Y) p := p0 for _, s := range w.Text { p, _ = fc.DrawString(string(s), p) if int(p.X>>8) > rct.Max.X-w.Padding.Max.X-w.Padding.Min.X { p.X = p0.X p.Y += raster.Fix32(lineHeight * 256) } } var texture gl.Texture if bg != nil { texture = gl.GenTexture() texture.Bind(gl.TEXTURE_2D) gl.ActiveTexture(gl.TEXTURE0) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, bg.Rect.Dx(), bg.Rect.Dy(), 0, gl.RGBA, gl.UNSIGNED_BYTE, bg.Pix) } leftX := 2.0*float32(corner.X+w.Rect.Min.X)/float32(root.Rect.Dx()) - 1.0 leftY := 1.0 - 2.0*float32(corner.Y+w.Rect.Min.Y)/float32(root.Rect.Dy()) rightX := 2.0*float32(corner.X+w.Rect.Min.X)/float32(root.Rect.Dx()) - 1.0 rightY := 1.0 - 2.0*float32(corner.Y+w.Rect.Max.Y)/float32(root.Rect.Dy()) bottomX := 2.0*float32(corner.X+w.Rect.Max.X)/float32(root.Rect.Dx()) - 1.0 bottomY := 1.0 - 2.0*float32(corner.Y+w.Rect.Min.Y)/float32(root.Rect.Dy()) topX := 2.0*float32(corner.X+w.Rect.Max.X)/float32(root.Rect.Dx()) - 1.0 topY := 1.0 - 2.0*float32(corner.Y+w.Rect.Max.Y)/float32(root.Rect.Dy()) vertices := []float32{ leftX, leftY, rightX, rightY, bottomX, bottomY, topX, topY, } texturePoints := []float32{ 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, } s_picture := program.GetUniformLocation("s_picture") s_picture.Uniform1i(0) has_picture := program.GetUniformLocation("has_picture") if bg != nil { has_picture.Uniform1i(1) } else { has_picture.Uniform1i(0) } col := program.GetUniformLocation("color") r, g, b, a := w.Background.RGBA() col.Uniform4f(float32(r)/float32(0xFFFF), float32(g)/float32(0xFFFF), float32(b)/float32(0xFFFF), float32(a)/float32(0xFFFF)) gl.PixelStorei(gl.UNPACK_ALIGNMENT, gl.UNSIGNED_BYTE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) a_position := program.GetAttribLocation("a_position") a_position.AttribPointer(2, gl.FLOAT, false, 0, vertices) a_position.EnableArray() a_coord := program.GetAttribLocation("a_coord") a_coord.AttribPointer(2, gl.FLOAT, false, 0, texturePoints) a_coord.EnableArray() gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) gl.Flush() texture.Delete() } }) window.SwapBuffers() glfw.PollEvents() } }
func (block *Block) BuildTexture() { block.tex = glh.NewTexture(1024, 256) block.tex.Init() // TODO: use runtime.SetFinalizer() to clean up/delete the texture? glh.With(block.tex, func() { //gl.TexParameteri(gl.TEXTURE_2D, gl.GENERATE_MIPMAP, gl.TRUE) //gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) // TODO: Only try and activate anisotropic filtering if it is available gl.TexParameterf(gl.TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, MaxAnisotropy) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 1) }) for i := 0; i < 2; i++ { glh.With(&glh.Framebuffer{Texture: block.tex, Level: i}, func() { glh.With(glh.Attrib{gl.COLOR_BUFFER_BIT}, func() { gl.ClearColor(1, 0, 0, 0) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) }) viewport_proj := glh.Compound(glh.Attrib{gl.VIEWPORT_BIT}, glh.Matrix{gl.PROJECTION}) glh.With(viewport_proj, func() { gl.Viewport(0, 0, block.tex.W/(1<<uint(i)), block.tex.H/(1<<uint(i))) gl.LoadIdentity() //gl.Ortho(0, float64(tex.w), 0, float64(tex.h), -1, 1) gl.Ortho(-2, -2+WIDTH, 2, -2, -1, 1) glh.With(glh.Matrix{gl.MODELVIEW}, func() { gl.LoadIdentity() //gl.Hint(gl.LINES, gl.NICEST) //gl.LineWidth(4) /* glh.With(glh.Primitive{gl.LINES}, func() { gl.Color4f(1, 1, 1, 1) gl.Vertex2f(-2, 0) gl.Vertex2f(2, 0) }) */ gl.PointSize(4) glh.With(glh.Matrix{gl.MODELVIEW}, func() { gl.Translated(0, -2, 0) gl.Scaled(1, 4/float64(block.nrecords), 1) block.vertex_data.Render(gl.POINTS) }) /* gl.Color4f(0.5, 0.5, 1, 1) With(Primitive{gl.LINE_LOOP}, func() { b := 0.2 Squared(-2.1+b, -2.1+b, 4.35-b*2, 4.2-b*2) }) */ }) }) }) } //block.img = block.tex.AsImage() if !block.detail_needed { block.vertex_data = nil runtime.GC() } blocks_rendered++ }
func (t *Texture) SetFiltering(minFilter Filter, magFilter Filter) { t.Bind() gl.TexParameteri(t.target, gl.TEXTURE_MAG_FILTER, int(magFilter)) gl.TexParameteri(t.target, gl.TEXTURE_MIN_FILTER, int(minFilter)) }
func LoadSkybox() { gl.ActiveTexture(gl.TEXTURE0) if err := CheckGlError(); err != nil { panic(err) } t := gl.GenTexture() if err := CheckGlError(); err != nil { panic(err) } t.Bind(gl.TEXTURE_CUBE_MAP) if err := CheckGlError(); err != nil { panic(err) } const filename = "Skybox_tut13_384x256.png" img, err := LoadImage(filename) if err != nil { panic(err) } size := img.Bounds().Size() w := size.X h := size.Y if w/3 != h/2 { panic("incorrect aspect ratio") } s := h / 2 // Size of one face of the cube. targets := [...]gl.GLenum{ gl.TEXTURE_CUBE_MAP_NEGATIVE_X, gl.TEXTURE_CUBE_MAP_POSITIVE_X, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, gl.TEXTURE_CUBE_MAP_POSITIVE_Y, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, gl.TEXTURE_CUBE_MAP_POSITIVE_Z, } rs := []image.Rectangle{ image.Rect(0*s, 0*s, 1*s, 1*s), // 0 side. image.Rect(1*s, 0*s, 2*s, 1*s), // 1 side. image.Rect(2*s, 0*s, 3*s, 1*s), // 2 side. image.Rect(0*s, 1*s, 1*s, 2*s), // 3 bottom. image.Rect(1*s, 1*s, 2*s, 2*s), // 4 top. image.Rect(2*s, 1*s, 3*s, 2*s), // 5 side. } // redirect must end with 3 and 4. This places the floor at -z and the // sky at +z. // All the sides look properly oriented (grass down) on the +y side. // Considering that the sky is properly oriented the way it is, then // rectangle 5 contains the picture that matches it on the +y side. // Therefore, redirect must end with 5, 3, 4. // Problem now: all the other sides, and maybe the floor too, need to be // rotated in order to line up, that is having their sky on top. redirect := [...]int{0, 2, 1, 5, 3, 4} ID := matrix23{1, 0, 0, 1, 0, 0} ms := [...]matrix23{ matrix23{0, -1, 1, 0, 0, s - 1}, matrix23{0, 1, -1, 0, s - 1, 0}, matrix23{-1, 0, 0, -1, s - 1, s - 1}, ID, matrix23{-1, 0, 0, -1, s - 1, s - 1}, ID, } rgba := forceRGBA(img) for i, target := range targets { subimage := rgba.SubImage(rs[redirect[i]]) data := GlRgba(subimage, ms[i]) gl.TexImage2D( target, 0, // Mipmap level. gl.SRGB8_ALPHA8, // Format inside OpenGL. s, // Width. s, // Height. 0, // Border. Doc says it must be 0. gl.RGBA, // Format of the data that... gl.UNSIGNED_BYTE, // ... I give to OpenGL. data, // And the data itself. ) if err := CheckGlError(); err != nil { panic(err) } } const target = gl.TEXTURE_CUBE_MAP gl.GenerateMipmap(target) if err := CheckGlError(); err != nil { panic(err) } gl.TexParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) if err := CheckGlError(); err != nil { panic(err) } gl.TexParameteri(target, gl.TEXTURE_MAG_FILTER, gl.LINEAR) if err := CheckGlError(); err != nil { panic(err) } gl.TexParameteri(target, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE) if err := CheckGlError(); err != nil { panic(err) } gl.TexParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) if err := CheckGlError(); err != nil { panic(err) } gl.TexParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) if err := CheckGlError(); err != nil { panic(err) } t.Unbind(target) globaltexture = t }
func LoadTexture() { gl.ActiveTexture(gl.TEXTURE0) if err := CheckGlError(); err != nil { panic(err) } t := gl.GenTexture() if err := CheckGlError(); err != nil { panic(err) } const target = gl.TEXTURE_2D t.Bind(target) if err := CheckGlError(); err != nil { panic(err) } img, err := LoadImage("test.jpg") if err != nil { panic(err) } data := GlRgba(img, matrix23{1, 0, 0, 1, 0, 0}) size := img.Bounds().Size() gl.TexImage2D( target, 0, // Mipmap level. gl.SRGB8_ALPHA8, // Format inside OpenGL. size.X, // Width. size.Y, // Height. 0, // Border. Doc says it must be 0. gl.RGBA, // Format of the data that... gl.UNSIGNED_BYTE, // ... I give to OpenGL. data, // And the data itself. ) if err := CheckGlError(); err != nil { panic(err) } gl.GenerateMipmap(target) if err := CheckGlError(); err != nil { panic(err) } gl.TexParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) if err := CheckGlError(); err != nil { panic(err) } gl.TexParameteri(target, gl.TEXTURE_MAG_FILTER, gl.LINEAR) if err := CheckGlError(); err != nil { panic(err) } gl.TexParameteri(target, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE) if err := CheckGlError(); err != nil { panic(err) } gl.TexParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) if err := CheckGlError(); err != nil { panic(err) } t.Unbind(target) globaltexture = t }