I'm curious -- why do you need this effect?
It's too specific a feature to include in Slick. The best way to achieve this is through shaders.
You need to know a little about polar to Cartesian conversion:
http://www.youtube.com/watch?v=29VW-NAd3lAYou should also understand a little about shaders if you want to know how the following code works. That way, you can optimize it to your game rather than just blindly copy-pasting.
http://www.lighthouse3d.com/opengl/glsl/I've written a short example here for you, using the rect2polar shader source I described
in this thread.
Something to note: To account for non-power-of-two (NPOT) textures, which are pretty common in Slick games, as well as allowing getSubImage to be used, I've modified the texture coordinates using uniforms. Ideally you should be using vertex attributes, but that isn't as easy to integrate with Slick's image rendering. If all of your images for this shader are power-of-two, then you can do without the texOff/texSize uniforms, as well as their use in the shader.
PolarizeShaderTest.java
Code:
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.opengl.shader.ShaderProgram;
public class PolarizeShaderTest extends BasicGame {
public static void main(String[] args) throws SlickException {
new AppGameContainer(new PolarizeShaderTest(), 800, 600, false).start();
}
public PolarizeShaderTest() {
super("Polarize Test");
}
private ShaderProgram polarizeShader;
private Image image;
private boolean useShader, shaderSupported;
private final String VERT = "testdata/shaders/pass.vert";
private final String FRAG = "testdata/shaders/rect2polar.frag";
@Override
public void init(GameContainer container) throws SlickException {
container.getGraphics().setBackground(Color.gray);
//create a new image
//Slick's images will use texture unit zero by default
image = new Image("testdata/polar.png");
//if shaders are supported...
if (ShaderProgram.isSupported()) {
try {
//"Strict Mode" will throw errors if we try
//to set a uniform that does not exist
//or isn't used in the shader. For flexibility,
//let's turn this off.
ShaderProgram.setStrictMode(false);
//We can conveniently load a program like so:
polarizeShader = ShaderProgram.loadProgram(VERT, FRAG);
//we have to set up the uniforms tex0, texOff and texSize
polarizeShader.bind();
//this means we are sampling from our image
polarizeShader.setUniform1i("tex0", 0);
//we set up texOff/texSize to account for possible sub-regions
//this allows us to use Image.getSubImage, or NPOT images
float texW = image.getTextureWidth();
float texH = image.getTextureHeight();
float texX = image.getTextureOffsetX();
float texY = image.getTextureOffsetY();
polarizeShader.setUniform2f("texSize", texW, texH);
polarizeShader.setUniform2f("texOff", texX, texY);
//unbind the shader once we're done
polarizeShader.unbind();
//shader works.
shaderSupported = true;
useShader = true;
} catch (SlickException e) {
e.printStackTrace();
}
}
}
@Override
public void render(GameContainer container, Graphics g)
throws SlickException {
//activate the shader
if (shaderSupported && useShader)
polarizeShader.bind();
//now anything we draw will use our polarize shader
image.draw();
//disable the shader
if (shaderSupported && useShader)
polarizeShader.unbind();
String str = shaderSupported
? "Press space to toggle shader"
: "Shaders not supported!";
g.drawString(str, 10, 20);
}
@Override
public void update(GameContainer container, int delta)
throws SlickException {
if (container.getInput().isKeyPressed(Input.KEY_SPACE))
useShader = !useShader;
}
}
pass.vert
Code:
void main() {
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
rect2polar.frag
Code:
#version 120
uniform sampler2D tex0;
uniform vec2 texOff;
uniform vec2 texSize;
const float PI = 3.14159265358979323846264;
void main(void) {
vec2 texCoord = gl_TexCoord[0].st;
//account for Slick's Image sub-regions (and NPOT images)
texCoord = (texCoord-texOff)/texSize;
//rectangular to polar filter
vec2 norm = (1.0 - texCoord) * 2.0 - 1.0;
float theta = PI + atan(norm.x, norm.y);
float r = length(norm);
vec2 polar = 1.0 - vec2(theta/(2.0*PI), r);
//sample the texture using the new coordinates
vec4 color = texture2D(tex0, (polar+texOff)*texSize);
gl_FragColor = color;
}