public
Created

Simple implementation of a software shader; uploading RGBA data to a texture every frame.

  • Download Gist
RGBATextureTest.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
package mdesl.test;
 
import static org.lwjgl.opengl.GL11.glClearColor;
 
import java.nio.ByteBuffer;
 
import mdesl.graphics.Color;
import mdesl.graphics.SpriteBatch;
import mdesl.graphics.Texture;
 
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
 
public class RGBATextureTest extends SimpleGame {
 
public static void main(String[] args) throws LWJGLException {
Game game = new RGBATextureTest();
game.setDisplayMode(640, 480, false);
game.start();
}
 
final int TEX_SIZE = 256;
//our sprite batch
SpriteBatch batch;
//our procedural texture
Texture tex;
ByteBuffer buffer;
float time = 0;
SoftwareShader shader;
protected void create() throws LWJGLException {
super.create();
//create an empty texture
tex = new Texture(TEX_SIZE, TEX_SIZE, Texture.LINEAR, Texture.REPEAT);
buffer = BufferUtils.createByteBuffer(tex.getWidth() * tex.getHeight() * 4);
shader = new Kaliset();
glClearColor(0.5f, .5f, .5f, 1f);
batch = new SpriteBatch();
}
 
protected void render() throws LWJGLException {
time += this.getDeltaTime();
int w = tex.getWidth();
int h = tex.getHeight();
Color color = new Color();
buffer.clear(); //clear our RGBA buffer
for (int i=0; i<w * h; i++) {
//offset to (x, y)
int y = i / w;
int x = i - w*y;
shader.getPixelColor(x, y, w, h, time, color);
//place R, G, B, A bytes
buffer.put( (byte)(Math.min(255, Math.max(0, color.r*255))) )
.put( (byte)(Math.min(255, Math.max(0, color.g*255))) )
.put( (byte)(Math.min(255, Math.max(0, color.b*255))) )
.put( (byte)(Math.min(255, Math.max(0, color.a*255))) );
}
buffer.flip();
tex.upload(GL11.GL_RGBA, buffer);
super.render();
batch.begin();
batch.draw(tex, 0, 0);
batch.end();
}
 
// called to resize the display
protected void resize() throws LWJGLException {
super.resize();
// resize our batch with the new screen size
batch.resize(Display.getWidth(), Display.getHeight());
}
//emulates shaders in software
interface SoftwareShader {
/**
* Gets the pixel color for the specified input values, placing it in the "out" param.
*
* @param x the x position of this pixel
* @param y the y position of this pixel
* @param width the width of the texture in pixels
* @param height the height of the texture in pixels
* @param time a time offset for effects
* @param the output color
*/
public void getPixelColor(int x, int y, int width, int height, float time, Color out);
}
//Kaliset fractal
//https://bitbucket.org/sharow/pijockey/src/tip/shaders/kaliset.glsl
class Kaliset implements SoftwareShader {
public static final int ITERATIONS = 22;
public void getPixelColor(int x, int y, int width, int height, float time, Color out) {
float cx = (float)(-0.5 * (2.5 + Math.sin(time * 0.0025)) / 2.0 + 0.3);
float cy = (float)(-0.5 * (2.5 + Math.sin(time * 0.0025)) / 2.0 + 0.3);
float zx = (x / (float)width) * 3f - 1.5f;
float zy = (y / (float)height) * 3f - 1.5f;
float total = 0f;
float m = 0f;
for (int i=0; i<ITERATIONS; i++) {
float pm = m;
m = zx*zx + zy*zy;
zx = Math.abs(zx) / m + cx;
zy = Math.abs(zy) / m + cy;
total += (float)Math.exp(-1.0 / Math.abs(m - pm));
}
total = total / 20f;
out.r = total*.5f;
out.g = total;
out.b = (float)(total/Math.sin(Math.cos(time/10f)));
out.a = 1.0f;
}
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.