It looks like you're new here. If you want to get involved, click one of these buttons!
I wrote a colorizer function which changes a grayscale image to color and I would like to put it in a shader.
The colorizer function takes a array colors (of any length) and divides those over the 256 shades.
I would like the shader to work in a similar way if possible, so that I can simply pass in any nr of colors. I’m not sure how best to pass the colors and then check the nr of colors passed, which I need for dividing them evenly.
Test code below, I want to put the colorizer functionality into a shader.
-- Colorising
-- Use this function to perform your initial setup
function setup()
cols = {color(255, 255, 255, 255), color(255, 179, 0, 255), color(255, 22, 0, 255)}
originalImg = gradient(WIDTH*.5,HEIGHT*.5)
coloredImg = colorize(originalImg, cols)
end
function colorize(img, colors)
local nImg = image(img.width, img.height)
local dStep = 255/(#colors-1)
for i=1, img.width do
for j=1, img.height do
local pix = img:get(i,j)
local cr = pix % dStep / dStep -- color mix ratio
local ci = #colors - pix // dStep -1 -- color index
local r = pix / 255 -- transparency ratio
local newc = mix(colors[ci], colors[ci+1], 1-cr)
nImg:set(i,j, color(newc.r, newc.g, newc.b, r*255))
end
end
return nImg
end
function mix(v1, v2, r)
return (1-r) * v1 + r*v2
end
function gradient(w,h)
local img = image(w,h)
setContext(img)
fill(0,0)
strokeWidth(1)
for i=0, img.width do
local r = i/img.width
stroke(255, r*255)
ellipse(img.width/2, img.height/2, (1-r)*img.width)
end
setContext()
return img
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(0, 0, 0, 255)
-- This sets the line thickness
strokeWidth(5)
-- Do your drawing here
sprite(originalImg, WIDTH/2, originalImg.height/2)
sprite(coloredImg, WIDTH/2, HEIGHT-coloredImg.height/2)
end
Comments
After quite a bit of reading and fiddling I got most of the shader working, but I’m having trouble getting the colors in an array for easy retrieval.
Right now I pass three seperate colors to the shader, “shader.color1=color” etc, and I can acces them in the shader, however I need to get those colors in an array within the shader.
If I had the colors in an array it should be trivial to get the correct color, but I’m having trouble creating a color array within the fragment shader.
I tried passing the colors to a vec4 array and I tried creating the array in the shader. I also tried to use an array with floats for the rgb cols but no luck.
TLDR: I have the seperate colors in the fragment shader (as color1-color3). How do
I put these in an array? Or can I get them directly by variable name as they are numbered (“color”+1-3)?
I need to pick the color dynamicaly so I can’t hard code it.
@Kirl Here’s an example of passing 8 colors in a table to the shader. Slide the parameter to change the color.
EDIT: Just remember that arrays in Codea start at 1 and arrays in shaders start at 0.
I wouldn't pass the colours as an array. I would pass them as a colourmap texture.
Without codea in front of me, it would be something like:
This is a simplified version of a colour-mapping shader that I have on github.
Thanks @dave1707 , I’ll try it out tomorrow. Not sure what I was doing wrong by looking at it. Maybe because I was using vec4?
[edit] Ah I see, probably the way I tried calling the colors...
[edit2] Ah, and the way I defined the colors...
That sounds interesting @LoopSpace, can you explain the technique? An online search wasn’t as illuminating as I hoped.
The code seems pretty straightforward, but how would I make this colormap texture? Am I correctly assuming this is a 1 x 256 pix coloured strip?
The code that I actually use is slightly more intricate as it uses several strips. I create the colour map with this code:
Not all of that is standard Codea, but hopefully clear enough to see what's going on.
Thanks @LoopSpace and @dave1707 , I have my shader working and it works a treat for a beautifull and blazingly fast fire effect! I’ll do the colormap aproach next.
I’m not sure where the artifacts at the bottom come from (~0:32), it’s not transparency depth as I draw each flame directly to the image. Any ideas?
I have a problem with the colormap aproach, it seems the alpha channel of the colormap is ignored by the shader. I used the simple aproach as suggested above by @LoopSpace.
Example img below, bottom-left is the original img and bottom-right is the shaded img with the used colormap displayed above. As you can see it doesn’t fade out. The original/texture img as well as the colormap img fade to transparent.
I googled a bit and fumbled a bit but no dice.
@Kirl Can you post the code? It ought to pick up the alpha from the colour map. Or did you want it to pick up the alpha from the original image?
I've reproduced the issue. It's to do with how the mesh is blended onto the background. The alpha is being set, but Codea is treating the mesh as if the alpha is pre-multiplied. A possible fix is to set premultiplied to false on the texture image. That worked for me in my test case.
@LoopSpace @Kirl I modified the above code and came up with this. A colormap can still be passed, but I thought I’d change the colors with the sliders.
Thanks guys!
I got some funky results when I forgot to pass a colormap!