This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Yevano's profile picture

Shader-Style Graphics - I.e., Pretty Lights!

Started by Yevano, 10 September 2015 - 06:15 PM
Yevano #1
Posted 10 September 2015 - 08:15 PM
Link
pastebin get z4kWdiKh gfx

This graphics library is for creating fragment shader-style programs. Fragment shaders are programs which take as input a position on the screen and output a color for that pixel. Now, in ComputerCraft, we normally only have a 16 color palette to use, or maybe more if you consider some dithering techniques. However, this API allows you to setup your color palette, and it automatically maps the RGB colorspace to the palette you give it. This just means that you can talk about colors using RGB components and the rest gets handled by the color mapping algorithm.

Well that's nice, but what can you actually use this for? I think in this case, screenshots (and video!) work better than words.

Media
Spoiler#1
SpoilerVideo: http://yevano.me/shr...10_14-49-28.mp4


	local res = inputs[1]
	local t = inputs[2]
	local uv = div2(coord, res)
	uv.x = uv.x * res.x/res.y--*2/3
	uv.x = uv.x - res.x/res.y/2--*2/3/2
	uv.y = uv.y - 0.5
	local m = getRotMat2(t)
	local uv = mat2mulvec2(m, sub2(uv, vec2(0, 0)))
	return vec4((uv.x % 0.4)*5*(sin(t)+1)/2, (uv.y % 0.2)*5*(cos(t)+1)/2, 0, 1)

#2
SpoilerVideo: http://yevano.me/shr...10_14-52-40.mp4


local function shaderFunc(color, coord, inputs)
	local res = inputs[1]
	local t = inputs[2]
	local uv = div2(coord, res)
	return vec4(uv.x, uv.y, 0.5 + 0.5 * math.sin(t), 1)
end

#3
SpoilerVideo: http://yevano.me/shr...10_14-57-49.mp4


local function shaderFunc(color, coord, inputs)
	local res = inputs[1]
	local t = inputs[2]
	local uv = div2(coord, res)
	uv.x = uv.x * res.x/res.y--*2/3
	uv.x = uv.x - res.x/res.y/2--*2/3/2
	uv.y = uv.y - 0.5
	local m = getRotMat2(t)
	local uv = mat2mulvec2(m, sub2(uv, vec2(0, 0)))
	local c = vec4((uv.x % 0.4)*5*(sin(t)+1)/2, (uv.y % 0.2)*5*(cos(t)+1)/2, 0, 1)
	local d = length2(sub2(uv, vec2(0.3, 0)))
	if d < 0.4 then
		if d < 0.35 then
			return c
		end
		return vec4(1, 0, 1, 1)
	end
	return vec4(0, 0, 0, 1)
end

I'm going to add proper documentation for this soon, but for now, this well-commented test file should help anyone who wants to write some shaders. pastebin get Hzg5cCRF test

Let me know if you find this useful!
SquidDev #2
Posted 10 September 2015 - 08:57 PM
I like your RGB to Lua converter :)/>.

Seriously though, wow. Sure, it isn't the most complicated thing in the world but it looks awesome. I'm seeing the potential for some new screensavers here :)/>.
Yevano #3
Posted 11 September 2015 - 12:56 AM
After updating the API (reflected in the paste, btw) with some more GLSL functions, I was able to port over a pretty looking shader I found on shadertoy.
Mine: http://yevano.me/shr/2015-09-10_19-43-29.mp4
(Code)
Spoiler

local function shaderFunc(oldColor, fragCoord, inputs)
    local brightness = 3.
    local ray_brightness = 5.
    local gamma = 6.
    local spot_brightness = 1.5
    local ray_density = 6.
    local curvature = 90.
    local red =   1.8
    local green = 3.
    local blue =  .5
    local noisetype = 1
    local sin_freq = 6.

    local iResolution = inputs[1]
    local iGlobalTime = inputs[2]
    local fragColor

    local function hash(n) return fract(sin(n)*43758.5453) end

    local function noise(x)
        x = vec2(x.x, x.y)
        x = mul2s(x, 1.75)
        local p = vec2(floor(x.x), floor(x.y))
        local f = vec2(fract(x.x), fract(x.y))

        f = mul2(mul2(f, f), (sub2(vec2(3, 3), mul2s(f, 2))))

        local n = p.x + p.y*57.0

        local res = mix(mix( hash(n+  0.0), hash(n+  1.0),f.x),
                        mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y)
        return res
    end

    local m2 = { 0.80,  0.60, -0.60,  0.80 };
    local function fbm(p)
        p = vec2(p.x, p.y)
        local z=2.
        local rz = 0.
        p = mul2s(p, 0.25)
        for i = 1, 5 do
            if noisetype == 1 then
                rz = rz + abs((noise(p)-0.5)*2.)/z
            elseif noisetype == 2 then
                rz = rz + (sin(noise(p)*sin_freq)*0.5+0.5) /z
            else
                rz = rz + noise(p)/z
            end
            z = z*2.
            p = mat2mulvec2(m2, mul2s(p, 2)) -- may need to swap these
        end
        return rz
    end

    local function mainImage()
        local t = -iGlobalTime*0.03*4
        uv = sub2s(div2(fragCoord, iResolution), 0.5)
        uv.x = uv.x * iResolution.x/iResolution.y
        uv = add2s(mul2s(mul2s(uv, curvature), .05), 0.0001)

        local r = sqrt(dot2(uv, uv))
        local x = dot2(normalize2(uv), vec2(.5,0.)) + t
        local y = dot2(normalize2(uv), vec2(.0,.5)) + t

        --[[#ifdef YO_DAWG
        x = fbm(vec2(y*ray_density*0.5,r+x*ray_density*.2));
        y = fbm(vec2(r+y*ray_density*0.1,x*ray_density*.5));
        #endif]]

        local val
        val = fbm(vec2(r+y*ray_density,r+x*ray_density-y))
        val = smoothstep(gamma*.02-.1,ray_brightness+(gamma*0.02-.1)+.001,val)
        val = sqrt(val)

        local col = div3(vec3(val, val, val), vec3(red,green,blue))
        --col = clamp(sub3(vec3(1, 1, 1), col),0,1)
        col = vec3(
            clamp(1-col.x, 0, 1),
            clamp(1-col.y, 0, 1),
            clamp(1-col.z, 0, 1))

        --col = mix(col,vec3(1.),spot_brightness-r/0.1/curvature*200./brightness);
        col.x = mix(col.x, 1, spot_brightness-r/0.1/curvature*200./brightness)
        col.y = mix(col.y, 1, spot_brightness-r/0.1/curvature*200./brightness)
        col.z = mix(col.z, 1, spot_brightness-r/0.1/curvature*200./brightness)

        fragColor = vec4(col.x, col.y, col.z, 1.0)
    end

    mainImage()
    return fragColor
end

Original: https://www.shadertoy.com/view/lsSGzy

Now that would make a pretty nice screensaver. :)/>
ElvishJerricco #4
Posted 11 September 2015 - 05:48 AM
Wow, great work man. I'd always wondered about something like this. Didn't think the results could be this good.
Yevano #5
Posted 22 December 2015 - 08:58 AM
Because of the 1.7 update, sub-cell rendering with square pixels is now possible! Therefore, I implemented render strategies. Here are all the strategies:

NOTE: STRATEGY_TWO_CELL is not implemented yet.

STRATEGY_FULL_CELL: Renders each color result into a full cell.



Pros:
  • Can render with text, allowing one to implement some effects and even faked dithering to some extent.
Cons:
  • Although the shader can be rendered uniformly by using getUnstretchedResolution, the non-square cells are somewhat noticeable.
  • Low resolution. 51x19 on a standard screen.
STRATEGY_HEX_CELL: Combines six color results into one cell using special characters. If more than two different CC colors are converted from the color results, only the 2 most prevalent colors will be used, and results using a different color will be replaced with the most prevalent color.



Pros:
  • Square pixels.
  • Higher resolution. 102x57 on a standard screen. Interestingly, this changes the pixel width and height ratio from 51:19 to 34:19.
Cons:
  • Since only two colors can be displayed per cell, some quality may be lost.
STRATEGY_TWO_CELL: Uses the same approach as STRATEGY_HEX_CELL, except that cells are divided up into thirds. If the cell is on an odd row (starting at row 1), the top two thirds will be used for a whole color result and the bottom third will be used for the top half of the color result on the next pixel data row. Else, the inverse occurs.

Pros:
  • Square pixels.
  • (Slightly) Higher resolution: 51x28
  • Doesn't lose colors due to the two color per cell limit.
Cons:
  • If height resolution is not a multiple of 3, cells on the top or bottom will only be partially used.
Note that when using higher screen resolutions you may need to use a higher color palette resolution to avoid losing quality. While 16x16x16 works okay for full cell rendering, higher values should be used for sub-cell strategies. 32x32x32 usually looks good, and 64x64x64 should look great no matter what.

Pastebin files have been updated.
pastebin get z4kWdiKh gfx
pastebin get Hzg5cCRF test
Edited on 22 December 2015 - 09:31 AM
Bomb Bloke #6
Posted 22 December 2015 - 10:17 AM
Lookin' good, but shouldn't two-cell have a vertical resolution of 28?
Yevano #7
Posted 22 December 2015 - 10:30 AM
Lookin' good, but shouldn't two-cell have a vertical resolution of 28?

Ah yep good catch.
Creator #8
Posted 22 December 2015 - 11:09 AM
What can this be used for? Background?

Also, aren't shaders used as a filter? Like they modify certain pixels in a certain way.