I moved to a new URL! Check it out!

posts tagged with: otter

Dev Log: Shaders All Day

Dev Log: Shaders All Day
I've been taking an extended vacation in shader town lately, and so far I've been having a lot of fun! One of the things I was figuring out was how to take an image and remap all the colors to a gradient based on their luminosity (well, a sloppy way of estimating the luminosity.) This seems like a pretty powerful effect that could be used to really spice up effects. Yeah, I'm always thinking about how to make explosions better.

First I'll share the actual shader code that I'm working with right now. This is the shader that's being used for all of my full screen effects.
uniform sampler2D texture;
uniform sampler2D displacementMap;
uniform sampler2D paletteMap;
uniform sampler2D gradientMap;

void main() {
vec4 displacementPixel = texture2D(displacementMap, gl_TexCoord[0]);
vec4 palettePixel = texture2D(paletteMap, gl_TexCoord[0]);

vec2 pos = gl_TexCoord[0];
pos.x += (displacementPixel.r * 2.0 - 1.0) * 0.025 * displacementPixel.a;
pos.y -= (displacementPixel.g * 2.0 - 1.0) * 0.025 * displacementPixel.a;

// Get the displaced pixel.
vec4 pixel = texture2D(texture, pos);

// Proper grayscale conversion.
float gray = dot(pixel.rgb, vec3(0.299, 0.587, 0.114));

// Get the color from the gradient.
float gradientPos = mod(gray + palettePixel.g, 1);

vec4 gradientMapPixel = texture2D(gradientMap, new vec2(gradientPos, palettePixel.r));

// Mix the gradient with the pixel color based on the palette pixel.
pixel = mix(pixel, gradientMapPixel, palettePixel.a);

gl_FragColor = pixel * gl_Color;
}
Using Otter I can just apply this shader to the game's main Surface object and I'm ready to roll with special effects. This post is going to be image heavy, so I'll hide the rest of it behind the jump!

Dev Log: Shader Experiments

Dev Log: Shader Experiments
Since my break to work on the remaining bits of Otter I haven't really fallen back into the groove on working on my big game project yet. Yesterday I dedicated the day to playing around with shaders since I'm really interested in using them for all kinds of cool visual effects.

Image


This is what I ended up coming up with at the end of the day. First I was playing around with gradient maps for recoloring an image, and then I started to mess with displacement to make cool waves in the image. Finally I wanted to experiment with having a render texture that could be passed to the shader for dynamic effects.

Basically how this little program works is that there is the static image with a shader loaded. Then there's a Surface object that can be painted on with the mouse. The shader uses the texture from that Surface to affect the image in different ways.

Here's the full C# source:
using Otter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ShaderTesting {
class Program {
static void Main(string[] args) {
var image = new Image("pic.jpg");
var game = new Game("ShaderZ", image.Width, image.Height);

game.FirstScene = new TestScene();

game.Start();
}
}

class TestScene : Scene {

Image image = new Image("pic.jpg");
Image circle = new Image("circle.png");
Surface distortion;

public TestScene() {
AddGraphic(image);
distortion = new Surface(image.Width, image.Height);
circle.CenterOrigin();
circle.Blend = BlendMode.Add;
AddGraphic(distortion);
circle.Alpha = 0.1f;
distortion.Visible = false;
distortion.AutoClear = false;
}

public override void Update() {
base.Update();

if (Timer % 30 == 0) {
try {
image.Shader = new Shader("../../shader.frag");
}
catch(Exception e) {
Console.WriteLine("Shader error:");
Console.WriteLine(e.Message);
}
image.Shader.SetParameter("gradient", new Texture("gradient.png"));
}
if (Input.MouseButtonPressed(MouseButton.Right)) {
distortion.Clear();
}
image.Shader.SetParameter("time", Timer);
image.Shader.SetParameter("distortion", distortion.Texture);
image.Shader.SetParameter("offset", Util.SinScale(Timer, 0, 1));

if (Input.MouseButtonDown(MouseButton.Left)) {
Draw.SetTarget(distortion);
Draw.Graphic(circle, MouseX, image.Height - MouseY);
Draw.ResetTarget();
}
}

public override void Render() {
base.Render();

Draw.Circle(MouseX - 15, MouseY - 15, 30, Color.None, Color.Red, 2);
}
}
}

And the GLSL shader source:
sampler2D texture;
sampler2D gradient;
sampler2D distortion;
uniform float offset;
uniform float time;
uniform float mixfactor;

void main() {
vec2 pos = gl_TexCoord[0];
vec2 distortColor = texture2D(distortion, pos);
pos.x += distortColor.r * (sin(time * 0.1 + pos.x * 10) * 0.05);
pos.y -= distortColor.g * (cos(time * 0.1 + pos.y * 10) * 0.05);
vec4 color = texture2D(texture, pos);

float gray = (color.r + color.g + color.b) / 3;

vec4 gradientColor = texture2D(gradient, vec2(gray, offset));

gl_FragColor = mix(color, gradientColor, distortColor.r + distortColor.g);
}

You can download everything here. Note that you'll have to give it a reference to Otter to compile and run it yourself.

More Otter Updates

More Otter Updates
I've gotten myself into the bad habit of procrastinating on my game project by working on Otter some more!

I just pushed another wave of updates on the journey to the big 1.0.0.

* Text and RichText's rendering positions have been changed. The default origin will now be the top left most position of any text, instead of allowing for "bleed." This should make it simpler to deal with.

* The Tilemap class got a few updates including a performance boost for clearing tiles, and a final pass on tile layers. Everything in the Tilemap class should now be usable as intended.

* Documentation fixes and updates across the board.

* Debugger has been updated to adjust for the Text updates.

So at this point I think the only thing that's left is fixing whatever bugs come up. So if you hit any bugs in any point in Otter then please let me know on the forums!

Otter Updates

Otter Updates
Things are moving along for Otter, my SFML.Net based game making framework!

I pushed a lot of changes this week that is bringing it closer to the big version 1.0. I overhauled a lot of the code in the Graphics classes, fixed some bugs, and updated all of the documentation for mostly everything. I also went through and cleaned up a lot of the code and organized it into nifty regions.

Right now my plan is to just keep testing things for awhile yet to make sure there's no crazy show-stopping bugs before I publicly announce to the world that it's officially version 1.0. Some of my recent changes have not been tested that thoroughly yet, and there have been a few bug reports popping up that I've been fixing up, so I can only imagine there are more bugs lurking in the shadows.

As far as sprite batching goes, I decided that I'm holding off on official sprite batching support until after version 1.0. There is some stuff set up in the back end of things to turn on sprite batching, but there are a handful of bugs that need to be resolved first and I don't think I'm going to be able to get them squished quickly enough. Aside from that, my performance tests seem to indicate that sprite batching isn't really that helpful anyway.

If you're using Otter and encounter any bugs, you can let me know on the forums or directly on the BitBucket issue tracker.

Incoming Otter Updates

Incoming Otter Updates
Sorry for the total lack of posts over the past week. I guess I have gone into a heads-down mode for the updates I've been working on for Otter.

About a week and a half ago I went in and tore apart a lot of the code for Graphics and the sub classes. This resulted in rendering being totally messed up for awhile as I tried to figure out a good way to batch sprites using common SFML RenderStates.

So far this seems like a fruitless effort, as even when I have basic sprite batching working the performance remains exactly the same. If anything right now the bottleneck for rendering just seems to be iterating through all of the entities to render, so for now I'm going to hold off on officially supporting sprite batching until version 1.1 or higher.

I did make a pretty big breakthrough on Sunday and finished the last of the collision detection functions. The last ones on the list were all using the PixelCollider class. Some of the functions could be optimized better, but for now this will work for a version 1.0 release sometime in the near future. I don't imagine seeing the PixelCollider class being used that much anyway.

For the time being I'm going through every single class now and organizing it and documenting it (if I haven't done so already) Soon Otter will be a very neat organized package of code all set up with fancy regions and comments. Then that will bring me to the beta of (hopefully) version 1.0. If nothing goes horribly wrong, I would image Otter will be at 1.0 status in a few weeks!

It's not as exciting as working on an actual game, but there were some things lurking in the shadows of Otter that I needed to address before they came back and bit me later. Thanks to everyone that has been finding bugs and suggesting things for Otter! It's pretty awesome and terrifying to know that people out there are using the engine.

Dev Log: To Batch or not to Batch

Dev Log: To Batch or not to Batch
One of the things gnawing at me over the past few months is the rendering performance of Otter. So far it hasn't really been a problem, but I've only made a couple of low resolution prototypes and a game jam game with it so far. For my current project, a 1920 x 1080 resolution game, I started to worry about the rendering time as I add more and more assets to it.

So I was thinking "Hey maybe I can add some kinda sprite batching to Otter like XNA or Monogame has!" The basic concept is that it is very expensive to switch textures when rendering things with a GPU, so you take a bunch of sprites that all share the same texture and try to mash them together into one draw call from the video card. This way you can render all your sprites but you don't have to switch textures for every single one of them.

To start on this I basically tore down a bunch of rendering code in Otter. This was a few days ago, and since then I do have some sort of basic sprite batch working. In a little example I have 1000 sprites rendering with the same texture and as far as the video card knows it's actually only 2 renders... but so far I actually don't think this has affected performance at all!

I'm using SFML.Net for the core rendering of Otter. Everything that goes to the video card to show up on the screen goes through SFML's Draw functions. So far according to my small tests it seems that the video card isn't really having any issue switching textures a thousand times, but something before that is actually causing the slow down.

It seems that just going through and appending vertices to a vertex array in SFML.Net is just really slow. For example Otter's RichText class suffers from a pretty big performance hit if it's used to render a lot of text, like enough letters to cover the entire screen. This is pretty odd since RichText.cs in Otter is pretty much a copy of SFML's own text class from the C++ source! Almost the same code in C# runs almost 10x slower than C++, and of course this is not a big surprise since C# has a bunch of extra stuff with the managed memory and garbage collection. Still, it is pretty discouraging to realize. (Another tough one is the Tilemap class, which will suffer from big slow down during real time modification of a huge tilemap due to the rebuilding of the VertexArray!)

So right now I'm still reorganizing a bunch of code in Otter's rendering stuff. Hopefully the API will remain mostly unchanged, but right now my hope is that using texture atlases in Otter becomes smoother and actually has a performance benefit. Yay programming.