Skip to content

Instantly share code, notes, and snippets.

@nasser
Created June 11, 2018 20:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nasser/30c5304fa4ea945d33a46097055121d4 to your computer and use it in GitHub Desktop.
Save nasser/30c5304fa4ea945d33a46097055121d4 to your computer and use it in GitHub Desktop.
// https://github.com/tgsstdio/OpenTK-Demos/blob/master/ComputeDemo/Demo.cs
using System;
using OpenTK.Graphics.OpenGL;
using OpenTK;
using OpenTK.Graphics;
namespace Pico
{
public class Demo
{
private int _mRenderProgramId;
public void Initialize()
{
_mRenderProgramId = SetupRenderProgram();
}
static uint _bufferWidth = 128;
static uint[] _frameBuffer = new uint[_bufferWidth * _bufferWidth];
static int _frameBufferLocation;
static void Set(int x, int y, uint c)
{
if (x >= _bufferWidth || y >= _bufferWidth || x < 0 || y < 0)
return;
_frameBuffer[(x % _bufferWidth) + y * _bufferWidth] = c;
}
// https://en.wikipedia.org/wiki/Midpoint_circle_algorithm
static void Circle(int x0, int y0, int radius, uint c)
{
int x = radius - 1;
int y = 0;
int dx = 1;
int dy = 1;
int err = dx - (radius << 1);
while (x >= y)
{
Set(x0 + x, y0 + y, c);
Set(x0 + y, y0 + x, c);
Set(x0 - y, y0 + x, c);
Set(x0 - x, y0 + y, c);
Set(x0 - x, y0 - y, c);
Set(x0 - y, y0 - x, c);
Set(x0 + y, y0 - x, c);
Set(x0 + x, y0 - y, c);
if (err <= 0)
{
y++;
err += dy;
dy += 2;
}
if (err > 0)
{
x--;
dx += 2;
err += dx - (radius << 1);
}
}
}
// https://en.wikipedia.org/wiki/Midpoint_circle_algorithm
static void FilledCircle(int x0, int y0, int radius, uint c)
{
int x = radius;
int y = 0;
int dx = 1;
int dy = 1;
int err = dx - (radius << 1);
while (x >= y)
{
Line(x0 + x, y0 + y, x0 - x, y0 + y, c);
Line(x0 + y, y0 + x, x0 - y, y0 + x, c);
Line(x0 - x, y0 - y, x0 + x, y0 - y, c);
Line(x0 + y, y0 - x, x0 - y, y0 - x, c);
if (err <= 0)
{
y++;
err += dy;
dy += 2;
}
if (err > 0)
{
x--;
dx += 2;
err += dx - (radius << 1);
}
}
}
// https://stackoverflow.com/questions/11678693/all-cases-covered-bresenhams-line-algorithm
static void Line(int x0, int y0, int x1, int y1, uint c)
{
int w = x1 - x0;
int h = y1 - y0;
int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0;
if (w < 0) dx1 = -1;
else if (w > 0) dx1 = 1;
if (h < 0) dy1 = -1;
else if (h > 0) dy1 = 1;
if (w < 0) dx2 = -1;
else if (w > 0) dx2 = 1;
int longest = Math.Abs(w);
int shortest = Math.Abs(h);
if (!(longest > shortest))
{
longest = Math.Abs(h);
shortest = Math.Abs(w);
if (h < 0) dy2 = -1;
else if (h > 0) dy2 = 1;
dx2 = 0;
}
int numerator = longest >> 1;
for (int i = 0; i <= longest; i++)
{
Set(x0, y0, c);
numerator += shortest;
if (!(numerator < longest))
{
numerator -= longest;
x0 += dx1;
y0 += dy1;
}
else
{
x0 += dx2;
y0 += dy2;
}
}
}
static float[] palette =
{
40 / 255f, 0 / 255f, 40 / 255f,
29 / 255f, 43 / 255f, 83 / 255f,
126 / 255f, 37 / 255f, 83 / 255f,
0 / 255f, 135 / 255f, 81 / 255f,
171 / 255f, 82 / 255f, 54 / 255f,
95 / 255f, 87 / 255f, 79 / 255f,
194 / 255f, 195 / 255f, 199 / 255f,
255 / 255f, 241 / 255f, 232 / 255f,
255 / 255f, 0 / 255f, 77 / 255f,
255 / 255f, 163 / 255f, 0 / 255f,
255 / 255f, 236 / 255f, 39 / 255f,
0 / 255f, 228 / 255f, 54 / 255f,
41 / 255f, 173 / 255f, 255 / 255f,
131 / 255f, 118 / 255f, 156 / 255f,
255 / 255f, 204 / 255f, 170 / 255f,
255 / 255f, 119 / 255f, 168 / 255f,
};
static Random rnd = new Random();
private static float t = 0;
private static int[] l = {10, 9, 8, 2, 1};
public void Draw1(int w, int h)
{
Array.Clear(_frameBuffer, 0, _frameBuffer.Length);
rnd = new Random(0);
for (int m = 0; m < 99; m++)
{
var x = rnd.Next(8) - 4;
var z = rnd.Next(8) - 4;
var y = rnd.Next(14) - 7;
for (int n = 4; n >= 0; n--)
{
var a = t / 4 + n * 0.1;
var c = Math.Cos(a) * x - Math.Sin(a) * z;
var d = Math.Sin(a) * x - Math.Cos(a) * z + 7;
var g = 64 + (c * 64) / d;
var hh = 64 + (y * 64) / d;
FilledCircle((int) g, (int) hh, (int) Math.Max((7 - d) + n / 2, 0), (uint) l[4 - n]);
}
}
t += 0.1f;
/////////
GL.UseProgram(_mRenderProgramId);
GL.BindBuffer(BufferTarget.UniformBuffer, _frameBufferLocation);
GL.BufferSubData(BufferTarget.UniformBuffer, IntPtr.Zero, sizeof(uint) * _frameBuffer.Length, _frameBuffer);
GL.Uniform2(GL.GetUniformLocation(_mRenderProgramId, "screen"), (float) w, (float) h);
GL.Uniform1(GL.GetUniformLocation(_mRenderProgramId, "width"), _bufferWidth);
GL.Uniform3(GL.GetUniformLocation(_mRenderProgramId, "palette"), palette.Length / 3, palette);
GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
}
public void Draw(int w, int h)
{
var f = 0.15 * t;
Array.Clear(_frameBuffer, 0, _frameBuffer.Length);
for (int i = 0; i < 128; i++)
{
Line(0, i, i, 0, (uint) ((i * 2 + t * 8) % 16));
Line(128, i, i, 128, (uint) ((i * 2 + t * 8) % 16));
}
for (int j = 1; j < 32; j++)
{
for (int i = 2; i < 10; i++)
{
var y = 0.2 - i / 5.0;
var g = y * y * 0.3 + (Math.Sin(f) + 1) * 0.75;
var k = j / 2.0;
var ww = Math.Cos(f + k) * g - Math.Sin(f + k) * g;
var q = Math.Sin(f + k) * g + Math.Cos(f + k) * g + 5;
var a = 64 + 64 * ww / q;
var b = 64 + 64 * y / q + Math.Sin(0.25 * (f + k + a)) * (Math.Cos(f) * 10);
FilledCircle((int) a - 2, (int) b - 2, (int) (6 - q), 0);
FilledCircle((int) a - 2, (int) (64 - b + 64) - 2, (int) (6 - q), 0);
FilledCircle((int) a, (int) b, (int) (6 - q), (uint) (1 + (i % 2)));
FilledCircle((int) a, (int) (64 - b + 64), (int) (6 - q), (uint) (8 + ((i - 2) % 7)));
}
}
t += 0.1f;
/////////
GL.UseProgram(_mRenderProgramId);
GL.BindBuffer(BufferTarget.UniformBuffer, _frameBufferLocation);
GL.BufferSubData(BufferTarget.UniformBuffer, IntPtr.Zero, sizeof(uint) * _frameBuffer.Length, _frameBuffer);
GL.Uniform2(GL.GetUniformLocation(_mRenderProgramId, "screen"), (float) w, (float) h);
GL.Uniform1(GL.GetUniformLocation(_mRenderProgramId, "width"), _bufferWidth);
GL.Uniform3(GL.GetUniformLocation(_mRenderProgramId, "palette"), palette.Length / 3, palette);
GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
}
private int SetupRenderProgram()
{
int progHandle = GL.CreateProgram();
int vp = GL.CreateShader(ShaderType.VertexShader);
int fp = GL.CreateShader(ShaderType.FragmentShader);
const string vpSrc = @"#version 430
in vec2 pos;
void main() {
gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);
}";
const string fpSrc = @"#version 430
out vec4 color;
uniform vec2 screen;
uniform uint width;
uniform vec3 palette[16];
layout (binding=0, packed) uniform pixelBufferLocation {
uint pixelBuffer [16384];
};
void main() {
float smallest_side = min(screen.y, screen.x);
float biggest_side = max(screen.y, screen.x);
float scale = smallest_side / width;
vec2 padding = vec2(0.0);
if(screen.x <= screen.y)
padding.y = (biggest_side - smallest_side) / 2.0;
else
padding.x = (biggest_side - smallest_side) / 2.0;
int ix = int((gl_FragCoord.x - padding.x) / scale);
int iy = int((gl_FragCoord.y - padding.y) / scale) * int(width);
if(ix < 0 || ix >= width || iy < 0 || iy > width*width) {
color = vec4(0.0);
} else {
int idx = ix + iy;
uint c = pixelBuffer[idx];
color = vec4(palette[c], 1.0);
}
}";
GL.ShaderSource(vp, vpSrc);
GL.ShaderSource(fp, fpSrc);
GL.CompileShader(vp);
int rvalue;
GL.GetShader(vp, ShaderParameter.CompileStatus, out rvalue);
if (rvalue != (int) All.True)
{
Console.WriteLine("Error in compiling vp");
Console.WriteLine((All) rvalue);
Console.WriteLine(GL.GetShaderInfoLog(vp));
}
GL.AttachShader(progHandle, vp);
GL.CompileShader(fp);
GL.GetShader(fp, ShaderParameter.CompileStatus, out rvalue);
if (rvalue != (int) All.True)
{
Console.WriteLine("Error in compiling fp");
Console.WriteLine((All) rvalue);
Console.WriteLine(GL.GetShaderInfoLog(fp));
}
GL.AttachShader(progHandle, fp);
GL.BindFragDataLocation(progHandle, 0, "color");
GL.LinkProgram(progHandle);
GL.GetProgram(progHandle, GetProgramParameterName.LinkStatus, out rvalue);
if (rvalue != (int) All.True)
{
Console.WriteLine("Error in linking sp");
Console.WriteLine((All) rvalue);
Console.WriteLine(GL.GetProgramInfoLog(progHandle));
}
GL.UseProgram(progHandle);
GL.Uniform1(GL.GetUniformLocation(progHandle, "srcTex"), 0);
var vertArray = GL.GenVertexArray();
GL.BindVertexArray(vertArray);
var posBuf = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, posBuf);
float[] data =
{
-1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, -1.0f,
1.0f, 1.0f
};
IntPtr dataSize = (IntPtr) (sizeof(float) * 8);
GL.BufferData(BufferTarget.ArrayBuffer, dataSize, data, BufferUsageHint.StreamDraw);
int posPtr = GL.GetAttribLocation(progHandle, "pos");
GL.VertexAttribPointer(posPtr, 2, VertexAttribPointerType.Float, false, 0, 0);
GL.EnableVertexAttribArray(posPtr);
_frameBufferLocation = GL.GenBuffer();
GL.BindBuffer(BufferTarget.UniformBuffer, _frameBufferLocation);
GL.BufferData(BufferTarget.UniformBuffer, sizeof(uint) * _frameBuffer.Length, _frameBuffer,
BufferUsageHint.StreamDraw);
var blockIndex = GL.GetUniformBlockIndex(progHandle, "pixelBufferLocation");
GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, _frameBufferLocation); // TODO 0??
GL.UniformBlockBinding(progHandle, blockIndex, 0); // TODO 0??
GL.GenTexture();
return progHandle;
}
}
static class MainClass
{
static void StatusPrint(StringName n)
{
Console.WriteLine("{0}: {1}", n, GL.GetString(n));
}
static void StatusPrint(GetPName n)
{
Console.WriteLine("{0}: {1}", n, GL.GetInteger(n));
}
[STAThread]
public static void Main(string[] args)
{
const int width = 1024 * 4;
const int height = 1024 * 4;
using (var game = new GameWindow(width, height, GraphicsMode.Default, "Pico", GameWindowFlags.Default,
DisplayDevice.Default, 4, 5, GraphicsContextFlags.Default))
{
Demo d = new Demo();
StatusPrint(GetPName.MaxUniformBlockSize);
game.Load += (sender, e) =>
{
// setup settings, load textures, sounds
d.Initialize();
game.VSync = VSyncMode.On;
StatusPrint(StringName.Renderer);
StatusPrint(StringName.ShadingLanguageVersion);
StatusPrint(StringName.Vendor);
StatusPrint(StringName.Version);
StatusPrint(GetPName.MaxFragmentUniformComponents);
StatusPrint(GetPName.MaxFragmentUniformVectors);
StatusPrint(GetPName.MaxUniformBlockSize);
};
game.RenderFrame += (sender, e) =>
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
d.Draw(game.Width, game.Height);
game.SwapBuffers();
// Console.WriteLine(game.RenderFrequency);
};
game.Resize += (sender, e) => { GL.Viewport(0, 0, game.Width, game.Height); };
game.Run(60.0);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment