Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Repeating a texture - does Render Target support @2x and @4x texture packs? — Gideros Forum

Repeating a texture - does Render Target support @2x and @4x texture packs?

NinjadoodleNinjadoodle Member
edited March 2016 in General questions
Hi guys

I have a 32x32 texture in one of my texture packs and I would like to repeat it horizontally and vertically, to fill the screen.

I've had a look at various code snippets on the forum, but nothing seems to be working for me.

Could someone show me the correct way to write this up, please :)

Thank you in advance!

Comments

  • You can draw a shape with screen width and height. Then fill it with the texture.
  • NinjadoodleNinjadoodle Member
    edited March 2016
    Hi @mertocan

    Thank you for your reply - I've tried, but I can seem to get the right syntax for setting up the texture using a texture pack.

    I can make this work with a single image, but not using a texture pack.
    local wallpaper = Texture.new("media/bgStripesBlue.png", true, {wrap = Texture.REPEAT})
    local block = Shape.new()
    block:setFillStyle(Shape.TEXTURE, wallpaper)
    block:beginPath(Shape.NON_ZERO)
    block:lineTo(320, 0)
    block:lineTo(320, 320)
    block:lineTo(0, 320)
    block:lineTo(0, 0)
    block:closePath()
    block:endPath()
    stage:addChild(block)
    If anyone knows how to do this, that would be awesome :)
  • antixantix Member
    @Ninjadoodle - your code works fine for me. Are you using a version of Gideros that supports texture wrapping?
  • Hi @antix

    Sorry, the code I posted above is the code I 'know' how to write - using a single image. This works fine.

    I can't however get it working, when pulling the image out from a texture pack. Nothing I've tried works.
  • For that, i think you need to use RenderTarget, because texture pack is somehow not a texture object.

  • hgy29hgy29 Maintainer
    edited March 2016
    I don't know if it is possible to repeat a part of a texture. I'll check if some api exists for that in OpenGL/DirectX. I have the same issue when trying to tile/repeat non-power-of-two textures.

    EDIT: This can be done with shaders, would it be worth it to add two more shaders to gideros core to handle this ?
  • NinjadoodleNinjadoodle Member
    edited March 2016
    Hi @hgy29 and @tkhnoman

    Thanks for the replies!

    How would you guys go about handling this ...

    Is it better to have a bunch of small 32x32 images for use as repeated backgrounds - separate from the levels texture pack - meaning the level will have to load a texture pack and another small image.

    OR

    Having a large background image, but as a part of the levels texture pack - this time the level only has to load the texture pack (which will be bigger in dimensions).

    Which is the better, more efficient way to do it?
  • antixantix Member
    I would use a RenderTarget for the repeating texture. Then all your backgrounds casn still be stored in your Atlas.
  • Hi @antix

    Any chance you could show me a little snippet of how this is done. I've had a look around the forums and can't seem to get it right.

    Thank you very much in advance!
  • I think i can't kind of give you any code snippet since i use kind of wrapper already, but i can explain.

    1. Create a sprite, with the texture pack just like you usually create it, don't add to stage
    2. Create a RenderTarget with a size of that sprite
    3. Then do this:
    renderObject:clear(0,0)
    renderObject:draw(yourCreatedSprite)

    There, you can use that renderObject just like texture, so you can use it like this:
    block:setFillStyle(Shape.TEXTURE, renderObject)
  • i think @tkhnoman's summary should be not hard to follow. for the specifics of how to use rendertarget let me point you to my tutorial:
    http://www.indiedb.com/tutorials/clipping-in-gideros-with-rendertarget
    it should be useful, although the illustrated use case is not the one you are looking for.
  • antixantix Member
    edited March 2016
    I think the issue here is that the RenderTarget does not seem to want to wrap, instead it just paints one tile in the shape, not many as @Ninjadoodle was wanting.

    RenderTarget.new() does not seem to support the options table so it can't be set to repeat from what I can see.
  • NinjadoodleNinjadoodle Member
    edited March 2016
    Thanks a lot for your help guys, I really appreciate it!

    It seems like the only way to do this, is to use an image separate from the texture pack?

    In this case, would you recommend ...

    A small 32x32 image for use as a repeated background - separate from the levels texture pack - meaning the level will have to load a texture pack and another small image.

    OR

    Having a large background image, but as a part of the levels texture pack - this time the level only has to load the texture pack (which will be bigger in dimensions).

    Which would be faster / more efficient?
  • antixantix Member
    edited March 2016
    @Ninjadoodle - You could keep your texture in the atlas and make a RenderTarget the size you want, filled with your pattern. You could then just make a BitMap using the RenderTarget Texture, or a Shape if you liked...
    TILE_WIDTH = 64
    TILE_HEIGHT = 64
     
    BACKDROP_WIDTH = 320
    BACKDROP_HEIGHT = 256
     
    local texture = Texture.new("Untitled.png", true) -- TEXTURE ATLAS
    local region = TextureRegion.new(texture, 0, 0, TILE_WIDTH, TILE_HEIGHT) -- REGION INSIDE ATLAS
    local tile = Bitmap.new(region) -- TILE TO DRAW
    local rt = RenderTarget.new(BACKDROP_WIDTH, BACKDROP_HEIGHT, true)
     
    for r = 0, BACKDROP_HEIGHT / TILE_HEIGHT - 1 do -- ROWS
    	tile:setY(r * TILE_HEIGHT)
    	for c = 0, BACKDROP_WIDTH / TILE_WIDTH - 1 do -- COLUMNS
    		tile:setX(c * TILE_WIDTH)
    		rt:draw(tile) -- DRAW TILE IN RENDERTARGET AT X,Y
    	end
    end
     
    local backDrop = Bitmap.new(rt) -- CREATE BACKDROP BITMAP FROM RENDERTARGET
    stage:addChild(backDrop)
  • tkhnomantkhnoman Member
    edited March 2016
    Hmm... i see. I haven't tried the shape
    How about mesh:
     
    function tableAdd(tableGet,arrayGet)
    	for i = 1,#arrayGet do
    		table.insert(tableGet,arrayGet[i])
    	end
    end
     
     
    local texturew,textureh = 100,100
     
    local sizeW,sizeH =3,5
     
    local vertexArray = {}
    local textureArray = {}
    local indexArray = {}
    for y = 0,sizeH - 1  do
    	for x = 0,sizeW - 1  do
    		local xnow,ynow = x * texturew,y * textureh
    		tableAdd(vertexArray,{xnow,ynow,		xnow + texturew,ynow,		xnow,ynow + textureh,		xnow + texturew,ynow + textureh,})
    		tableAdd(textureArray,{0,0,		texturew,0,		0,textureh,		texturew,textureh,})
    		local nodeGet = ((y * sizeW + x ) * 4) + 1
    		tableAdd(indexArray,{nodeGet, nodeGet + 1, nodeGet + 3, nodeGet ,nodeGet + 3, nodeGet + 2})
    		print(nodeGet, nodeGet + 1, nodeGet + 3, nodeGet ,nodeGet + 3, nodeGet + 2)
    	end
    end
     
    s = Mesh.new()
    s:setVertexArray(vertexArray)
    s:setTextureCoordinateArray(textureArray)
    s:setIndexArray(indexArray)
    s:setTexture(render)
     
    stage:addChild(s)
    edit : This is not complete code, i just snip it from my code, so "render" is generated before
  • NinjadoodleNinjadoodle Member
    edited March 2016
    Hi @antix and @tkhnoman

    Thank you heaps for the snippet! I however don't really understand where the texture atlas is being setup.

    @antix - it looks like this line is pulling the texture ...
    local texture = Texture.new("Untitled.png", true)
    ... I don't however understand how I can make this work with an atlas. Every time I try to create a texture from an atlas I get errors.

    I tried replacing the line with ...
    local texture = Texture.new(self.pack:getTextureRegion("bgStripesBlue.png"))
    and also ...
    local texture = Bitmap.new(self.pack:getTextureRegion("bgStripesBlue.png"))
    but neither of them work.

    Thank you again for your help!

    fyi - I also use @2x and @4x sprite sheets
  • antixantix Member
    @ tkhnoman - Yep that does work (once you create a RenderTarget containing the graphic above it), nice. I have no idea which method is more efficient or which is faster (if those are even considerations in this case).

    One day I must look at the Mesh class :)
  • NinjadoodleNinjadoodle Member
    edited March 2016
    Hi @tkhnoman

    I've followed your above instructions and this is what I have ...
    self.wallpaper = Bitmap.new(self.pack:getTextureRegion("bgStripesBlue.png"))
     
    self.renderObject = RenderTarget.new(32, 32, true)
    self.renderObject:clear(0,0)
    self.renderObject:draw(self.wallpaper)
     
    self.block = Shape.new()
    self.block:setFillStyle(Shape.TEXTURE, self.renderObject)
    self.block:beginPath(Shape.NON_ZERO)
    self.block:lineTo(320, 0)
    self.block:lineTo(320, 320)
    self.block:lineTo(0, 320)
    self.block:lineTo(0, 0)
    self.block:closePath()
    self.block:endPath()
    fg:addChild(self.block)
    This still doesn't work tho ...

    I only get a single square on the screen :(
  • NinjadoodleNinjadoodle Member
    edited March 2016
    Hi @tkhnoman

    Thank you for your mesh method - I managed to get my texture to tile.

    I however don't think it is taking my @2x and @4x sprite sheets into consideration, as it spits the texture out extremely tiny when @2x or @4x textures are being used.

    Is this a limitation of this method?
  • antixantix Member
    edited March 2016
    @Ninjadoodle - Ahh I see. Sorry, I don't use texture packs at all.

    In my programs I have my texture atlas which holds all my textures, and I have a table that describes individual regions inside the texture atlas. It's kind of like the texture pack but made manually.

    Maybe I should switch to texture packs? I don't know what the benefits really are.

    Anyway, I think you need to just replace the top two lines of code with..
    --local texture = Texture.new("Untitled.png", true) -- TEXTURE ATLAS
    --local region = TextureRegion.new(texture, 0, 0, TILE_WIDTH, TILE_HEIGHT) -- REGION INSIDE ATLAS
     
    local pack = TexturePack.new("atlas.txt", "atlas.png")
    local region = pack:getTextureRegion("u1.png")
    Of course, use your own names ;)
  • NinjadoodleNinjadoodle Member
    edited March 2016
    Hi @antix

    Cool thanks for the heads up :)

    I've tried the new way, and I can now get it working - however - there is the same problem as with the other snipped I posted about..

    I don't think this works with @2x, @4x atlases.

    The textures that are tiled are very tiny, and it looks like, its loading the smallest (@1x) texture when it should be displaying @4x.

    Anybody know whether I'm right thinking that this method (render target) doesn't support @2x and @4x scaling variants?

    Thanks again in advance!
  • tkhnomantkhnoman Member
    edited March 2016
    To tell the truth, i never us Gideros's automatic scaling. I don't like things that i can't control by myself.
    I checked scale factor by myself, and see which @2x, or such is fit for it, and scale it myself. That is why this is not going in to my consideration...


    @antix : Mesh is good... if you like playing with shader, but it have a limitation.
    For example, sometime if you use renderTarget in Mesh, and draw just once, it might be not drawn directly in time, it might need timer delay. Or another way is you need to prepare mesh first in the first load, and just setTexture in the stage load.
  • Hi @tkhnoman

    Thank for the reply. Looks like I'm just going to keep a separate image to use as a repeated texture for now. I like using the Gideros automatic scaling, and I can't seem to get the methods above working with it.

    If anybody can point out a different / better way, that would be awesome :)
  • YanYan Member
    edited December 2016
    Easiest way is to draw wrap byurself
    	local texturePack	= TexturePack.new("textures/Ground.txt", "textures/Ground.png", true)
    	local textureTile	= Bitmap.new(texturePack:getTextureRegion("ground.png"))
    	local renderTarget	= RenderTarget.new(edgePoints.rx, edgePoints.by, true)
     
    	for x=1, edgePoints.rx, 50 do
    		for y=1, edgePoints.by, 50 do
    			textureTile:setPosition(x, y)
    			renderTarget:draw(textureTile)
    		end
    	end
     
     
    	local shape = Shape.new()
    	shape:setFillStyle(Shape.TEXTURE, renderTarget)
    vk.com/yan_alex
  • SinisterSoftSinisterSoft Maintainer
    edited December 2016
    "
    I have a 32x32 texture in one of my texture packs and I would like to repeat it horizontally and vertically, to fill the screen.
    "

    Here is a snip of code from something I'm working on in my spare time, it repeats the texture to whatever dimensions I want.
    -- load the textures for different pitch patterns
    grass={}
    for loop=1,6 do
    	grass[loop]=Texture.new("grass/grass"..loop..".png",true,{wrap = Texture.REPEAT})
    end
    .
    .
    .
    -- create the grass sprite
    grassLayer=Pixel.new(0xffffff,1,pitchW,pitchH)
    .
    .
    .
    -- setup the grass sprite for this specific pitch
    grassLayer:setScale(1/s2)
    grassLayer:setWidth(w2*z2*s2)
    grassLayer:setHeight(h2*z2*s2)
    grassLayer:setAnchorPoint(0.5,0.5)
    grassLayer:setTexture(grass[g2])
    2016-12-09_13-44-55.png
    1430 x 790 - 2M
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
Sign In or Register to comment.