Skip to content
Browse files

updating tests, adding framebuffers

  • Loading branch information...
1 parent 2a352fd commit 3feb67b662c0e42c77bd88bf370ca3fa225f62d1 @mattdesl committed Dec 15, 2012
View
2 src/mdesl/graphics/Color.java
@@ -63,7 +63,7 @@
public final static Color ORANGE = new Color(255, 200, 0, 255);
/** The fixed colour dark magenta */
public final static Color MAGENTA = new Color(255, 0, 255, 255);
-
+
/** The red component [0.0 - 1.0]. */
public float r;
/** The green component [0.0 - 1.0]. */
View
188 src/mdesl/graphics/Framebuffer.java
@@ -0,0 +1,188 @@
+/**
+ * Copyright (c) 2012, Matt DesLauriers All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary
+ * form must reproduce the above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * * Neither the name of the Matt DesLauriers nor the names
+ * of his contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package mdesl.graphics;
+
+import static org.lwjgl.opengl.EXTFramebufferObject.GL_FRAMEBUFFER_EXT;
+import static org.lwjgl.opengl.EXTFramebufferObject.glBindFramebufferEXT;
+import static org.lwjgl.opengl.EXTFramebufferObject.glCheckFramebufferStatusEXT;
+import static org.lwjgl.opengl.EXTFramebufferObject.glDeleteFramebuffersEXT;
+import static org.lwjgl.opengl.EXTFramebufferObject.glFramebufferTexture2DEXT;
+import static org.lwjgl.opengl.EXTFramebufferObject.glGenFramebuffersEXT;
+import static org.lwjgl.opengl.GL11.glViewport;
+import static org.lwjgl.opengl.GL30.GL_COLOR_ATTACHMENT0;
+import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER;
+import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_COMPLETE;
+import static org.lwjgl.opengl.GL30.glDeleteFramebuffers;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.GLContext;
+
+/**
+ * A very thin wrapper around OpenGL Frame Buffer Objects, intended for
+ * 2D purposes. This uses GL_FRAMEBUFFER_EXT for GL 2.1 compatibility.
+ *
+ * @author davedes
+ */
+public class Framebuffer implements ITexture {
+
+ public static boolean isSupported() {
+ return GLContext.getCapabilities().GL_EXT_framebuffer_object;
+ }
+
+ /** The ID of the FBO in use */
+ protected int id;
+ protected Texture texture;
+ protected boolean ownsTexture;
+
+ Framebuffer(Texture texture, boolean ownsTexture) throws LWJGLException {
+ this.texture = texture;
+ this.ownsTexture = ownsTexture;
+ if (!isSupported()) {
+ throw new LWJGLException("FBO extension not supported in hardware");
+ }
+ texture.bind();
+ id = glGenFramebuffersEXT();
+ glBindFramebufferEXT(GL_FRAMEBUFFER, id);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ texture.getTarget(), texture.getID(), 0);
+ int result = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
+ if (result!=GL_FRAMEBUFFER_COMPLETE) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
+ glDeleteFramebuffers(id);
+ throw new LWJGLException("exception "+result+" when checking FBO status");
+ }
+ glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
+ }
+
+ /**
+ * Advanced constructor which creates a frame buffer from a texture; the framebuffer
+ * does not "own" the texture and thus calling dispose() on this framebuffer will not
+ * destroy the texture.
+ *
+ * @param texture the texture to use
+ * @throws LWJGLException if the framebuffer was not initialized correctly
+ */
+ public Framebuffer(Texture texture) throws LWJGLException {
+ this(texture, false);
+ }
+
+ /**
+ *
+ * @param width
+ * @param height
+ * @param filter
+ * @param wrap
+ * @throws LWJGLException
+ */
+ public Framebuffer(int width, int height, int filter, int wrap) throws LWJGLException {
+ this(new Texture(width, height, filter, wrap), true);
+ }
+
+ public Framebuffer(int width, int height, int filter) throws LWJGLException {
+ this(width, height, filter, Texture.DEFAULT_WRAP);
+ }
+
+ public Framebuffer(int width, int height) throws LWJGLException {
+ this(width, height, Texture.DEFAULT_FILTER, Texture.DEFAULT_WRAP);
+ }
+
+ public int getID() {
+ return id;
+ }
+
+ public int getWidth() {
+ return texture.getWidth();
+ }
+
+ public int getHeight() {
+ return texture.getHeight();
+ }
+
+ public Texture getTexture() {
+ return texture;
+ }
+
+ /**
+ * Binds the FBO and sets glViewport to the texture region width/height.
+ */
+ public void begin() {
+ if (id == 0)
+ throw new IllegalStateException("can't use FBO as it has been destroyed..");
+ glViewport(0, 0, getWidth(), getHeight());
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
+ //glReadBuffer(GL_COLOR_ATTACHMENT0);
+ }
+
+ /**
+ * Unbinds the FBO and resets glViewport to the display size.
+ */
+ public void end() {
+ if (id==0)
+ return;
+ glViewport(0, 0, Display.getWidth(), Display.getHeight());
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ }
+
+ /**
+ * Disposes this FBO without destroying the texture.
+ */
+ public void dispose() {
+ if (id==0)
+ return;
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glDeleteFramebuffersEXT(id);
+ if (ownsTexture)
+ texture.dispose();
+ id = 0;
+ //glReadBuffer(GL_BACK);
+ }
+
+ @Override
+ public float getU() {
+ return 0;
+ }
+
+ @Override
+ public float getV() {
+ return 1f;
+ }
+
+ @Override
+ public float getU2() {
+ return 1f;
+ }
+
+ @Override
+ public float getV2() {
+ return 0;
+ }
+}
View
4 src/mdesl/graphics/ITexture.java
@@ -40,8 +40,8 @@
public interface ITexture {
public Texture getTexture();
- public float getWidth();
- public float getHeight();
+ public int getWidth();
+ public int getHeight();
public float getU();
public float getV();
public float getU2();
View
108 src/mdesl/graphics/SpriteBatch.java
@@ -31,7 +31,6 @@
package mdesl.graphics;
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
-import static org.lwjgl.opengl.GL20.glUniform1i;
import java.nio.FloatBuffer;
import java.util.Arrays;
@@ -46,7 +45,6 @@
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.util.vector.Matrix4f;
-import org.lwjgl.util.vector.Vector2f;
/** @author Matt (mdesl) DesLauriers
* @author matheusdev */
@@ -94,16 +92,16 @@
private Color color = new Color();
private boolean drawing = false;
- static ShaderProgram getDefaultShader() throws LWJGLException {
- return defaultShader == null ? new ShaderProgram(DEFAULT_VERT_SHADER, DEFAULT_FRAG_SHADER,
- ATTRIBUTES) : defaultShader;
+ public static ShaderProgram getDefaultShader() throws LWJGLException {
+ return defaultShader == null ? (defaultShader = new ShaderProgram(DEFAULT_VERT_SHADER, DEFAULT_FRAG_SHADER,
+ ATTRIBUTES)) : defaultShader;
}
public SpriteBatch(ShaderProgram program) {
this(program, 1000);
}
- public SpriteBatch(ShaderProgram program, int size) {
+ public SpriteBatch(ShaderProgram program, int size) {
this.program = program;
// later we can do some abstraction to replace this with VBOs...
@@ -118,6 +116,11 @@ public SpriteBatch(ShaderProgram program, int size) {
resize(Display.getWidth(), Display.getHeight());
}
+ /**
+ * Creates a sprite batch with a default shader, shared across all sprite batches.
+ * @param size
+ * @throws LWJGLException
+ */
public SpriteBatch(int size) throws LWJGLException {
this(getDefaultShader(), size);
}
@@ -141,7 +144,7 @@ public Matrix4f getProjectionMatrix() {
* @param width
* @param height */
public void resize(int width, int height) {
- projMatrix = MathUtil.toOrtho2D(projMatrix, 0, 0, Display.getWidth(), Display.getHeight());
+ projMatrix = MathUtil.toOrtho2D(projMatrix, 0, 0, width, height);
updateUniforms();
}
@@ -205,6 +208,8 @@ public void updateUniforms(ShaderProgram program) {
* @param updateUniforms whether to call updateUniforms after changing the
* programs */
public void setShader(ShaderProgram program, boolean updateUniforms) {
+ if (program==null)
+ throw new NullPointerException("shader cannot be null; use getDefaultShader instead");
if (drawing) {
flush();
this.program.use();
@@ -222,6 +227,10 @@ public void setShader(ShaderProgram program) {
setShader(program, true);
}
+ public ShaderProgram getShader() {
+ return program;
+ }
+
public void begin() {
if (drawing)
throw new IllegalStateException("must not be drawing before calling begin()");
@@ -261,6 +270,16 @@ public void drawRegion(Texture tex, float srcX, float srcY, float srcWidth, floa
float v2 = (srcY + srcHeight) / tex.getHeight();
draw(tex, dstX, dstY, dstWidth, dstHeight, u, v, u2, v2);
}
+
+ public void drawRegion(TextureRegion region, float srcX, float srcY, float srcWidth, float srcHeight, float dstX, float dstY) {
+ drawRegion(region, srcX, srcY, srcWidth, srcHeight, dstX, dstY, srcWidth, srcHeight);
+ }
+
+ public void drawRegion(TextureRegion region, float srcX, float srcY, float srcWidth, float srcHeight,
+ float dstX, float dstY, float dstWidth, float dstHeight) {
+ drawRegion(region.getTexture(), region.getRegionX() + srcX, region.getRegionY() + srcY,
+ srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight);
+ }
public void draw(ITexture tex, float x, float y) {
draw(tex, x, y, tex.getWidth(), tex.getHeight());
@@ -270,23 +289,84 @@ public void draw(ITexture tex, float x, float y, float width, float height) {
draw(tex, x, y, width, height, tex.getU(), tex.getV(), tex.getU2(), tex.getV2());
}
- public void draw(ITexture tex, float x, float y, float width, float height, float u, float v,
+
+ public void draw(ITexture tex, float x, float y, float originX, float originY, float rotationRadians) {
+ draw(tex, x, y, tex.getWidth(), tex.getHeight(), originX, originY, rotationRadians);
+ }
+
+ public void draw(ITexture tex, float x, float y, float width, float height,
+ float originX, float originY, float rotationRadians) {
+ draw(tex, x, y, width, height, originX, originY, rotationRadians, tex.getU(), tex.getV(), tex.getU2(), tex.getV2());
+ }
+
+ public void draw(ITexture tex, float x, float y, float width, float height,
+ float originX, float originY, float rotationRadians,
+ float u, float v,
float u2, float v2) {
checkFlush(tex);
final float r = color.r;
final float g = color.g;
final float b = color.b;
final float a = color.a;
+
+ float x1,y1, x2,y2, x3,y3, x4,y4;
+
+ if (rotationRadians != 0) {
+ float scaleX = 1f;//width/tex.getWidth();
+ float scaleY = 1f;//height/tex.getHeight();
+
+ float cx = originX*scaleX;
+ float cy = originY*scaleY;
+
+ float p1x = -cx;
+ float p1y = -cy;
+ float p2x = width - cx;
+ float p2y = -cy;
+ float p3x = width - cx;
+ float p3y = height - cy;
+ float p4x = -cx;
+ float p4y = height - cy;
+
+ final float cos = (float) Math.cos(rotationRadians);
+ final float sin = (float) Math.sin(rotationRadians);
+
+ x1 = x + (cos * p1x - sin * p1y) + cx; // TOP LEFT
+ y1 = y + (sin * p1x + cos * p1y) + cy;
+ x2 = x + (cos * p2x - sin * p2y) + cx; // TOP RIGHT
+ y2 = y + (sin * p2x + cos * p2y) + cy;
+ x3 = x + (cos * p3x - sin * p3y) + cx; // BOTTOM RIGHT
+ y3 = y + (sin * p3x + cos * p3y) + cy;
+ x4 = x + (cos * p4x - sin * p4y) + cx; // BOTTOM LEFT
+ y4 = y + (sin * p4x + cos * p4y) + cy;
+ } else {
+ x1 = x;
+ y1 = y;
+
+ x2 = x+width;
+ y2 = y;
+
+ x3 = x+width;
+ y3 = y+height;
+
+ x4 = x;
+ y4 = y+height;
+ }
+
// top left, top right, bottom left
- vertex(x, y, r, g, b, a, u, v);
- vertex(x + width, y, r, g, b, a, u2, v);
- vertex(x, y + height, r, g, b, a, u, v2);
+ vertex(x1, y1, r, g, b, a, u, v);
+ vertex(x2, y2, r, g, b, a, u2, v);
+ vertex(x4, y4, r, g, b, a, u, v2);
// top right, bottom right, bottom left
- vertex(x + width, y, r, g, b, a, u2, v);
- vertex(x + width, y + height, r, g, b, a, u2, v2);
- vertex(x, y + height, r, g, b, a, u, v2);
+ vertex(x2, y2, r, g, b, a, u2, v);
+ vertex(x3, y3, r, g, b, a, u2, v2);
+ vertex(x4, y4, r, g, b, a, u, v2);
+ }
+
+ public void draw(ITexture tex, float x, float y, float width, float height, float u, float v,
+ float u2, float v2) {
+ draw(tex, x, y, width, height, x, y, 0f, u, v, u2, v2);
}
/** Renders a texture using custom vertex attributes; e.g. for different
View
57 src/mdesl/graphics/Texture.java
@@ -59,6 +59,7 @@
import java.nio.ByteBuffer;
import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.GLContext;
import de.matthiasmann.twl.utils.PNGDecoder;
@@ -71,11 +72,21 @@
* @author davedes */
public class Texture implements ITexture {
- protected int target = GL_TEXTURE_2D;
-
protected int id;
protected int width;
protected int height;
+
+ public static int toPowerOfTwo(int n) {
+ return 1 << (32 - Integer.numberOfLeadingZeros(n-1));
+ }
+
+ public static boolean isPowerOfTwo(int n) {
+ return (n & -n) == n;
+ }
+
+ public static boolean isNPOTSupported() {
+ return GLContext.getCapabilities().GL_ARB_texture_non_power_of_two;
+ }
// Some filters, included here for convenience
public static final int LINEAR = GL_LINEAR;
@@ -86,14 +97,21 @@
public static final int CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE;
public static final int REPEAT = GL_REPEAT;
+ public static final int DEFAULT_FILTER = NEAREST;
+ public static final int DEFAULT_WRAP = REPEAT;
+
+ protected Texture() {
+ //does nothing... for subclasses
+ }
+
/** Creates an empty OpenGL texture with the given width and height, where
* each pixel is transparent black (0, 0, 0, 0) and the wrap mode is
* CLAMP_TO_EDGE and the filter is NEAREST.
*
* @param width the width of the texture
* @param height the height of the texture */
public Texture(int width, int height) {
- this(width, height, NEAREST);
+ this(width, height, DEFAULT_FILTER);
}
/** Creates an empty OpenGL texture with the given width and height, where
@@ -104,7 +122,7 @@ public Texture(int width, int height) {
* @param height the height of the texture
* @param filter the filter to use */
public Texture(int width, int height, int filter) {
- this(width, height, filter, CLAMP_TO_EDGE);
+ this(width, height, filter, DEFAULT_WRAP);
}
/** Creates an empty OpenGL texture with the given width and height, where
@@ -115,7 +133,7 @@ public Texture(int width, int height, int filter) {
* @param filter the filter to use
* @param wrap the wrap mode to use */
public Texture(int width, int height, int filter, int wrap) {
- glEnable(target);
+ glEnable(getTarget());
id = glGenTextures();
this.width = width;
this.height = height;
@@ -127,14 +145,15 @@ public Texture(int width, int height, int filter, int wrap) {
}
public Texture(URL pngRef) throws IOException {
- this(pngRef, NEAREST);
+ this(pngRef, DEFAULT_FILTER);
}
public Texture(URL pngRef, int filter) throws IOException {
- this(pngRef, filter, CLAMP_TO_EDGE);
+ this(pngRef, filter, DEFAULT_WRAP);
}
public Texture(URL pngRef, int filter, int wrap) throws IOException {
+ //TODO: npot check
InputStream input = null;
try {
input = pngRef.openStream();
@@ -146,7 +165,7 @@ public Texture(URL pngRef, int filter, int wrap) throws IOException {
dec.decode(buf, width * 4, PNGDecoder.Format.RGBA);
buf.flip();
- glEnable(target);
+ glEnable(getTarget());
id = glGenTextures();
bind();
@@ -163,6 +182,10 @@ public Texture(URL pngRef, int filter, int wrap) throws IOException {
}
}
+ public int getTarget() {
+ return GL_TEXTURE_2D;
+ }
+
public int getID() {
return id;
}
@@ -179,7 +202,7 @@ protected void setUnpackAlignment() {
public void upload(int dataFormat, ByteBuffer data) {
bind();
setUnpackAlignment();
- glTexImage2D(target, 0, GL_RGBA, width, height, 0, dataFormat, GL_UNSIGNED_BYTE, data);
+ glTexImage2D(getTarget(), 0, GL_RGBA, width, height, 0, dataFormat, GL_UNSIGNED_BYTE, data);
}
/** Uploads a sub-image within this texture.
@@ -193,25 +216,25 @@ public void upload(int dataFormat, ByteBuffer data) {
public void upload(int x, int y, int width, int height, int dataFormat, ByteBuffer data) {
bind();
setUnpackAlignment();
- glTexSubImage2D(target, 0, x, y, width, height, dataFormat, GL_UNSIGNED_BYTE, data);
+ glTexSubImage2D(getTarget(), 0, x, y, width, height, dataFormat, GL_UNSIGNED_BYTE, data);
}
public void setFilter(int filter) {
bind();
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
+ glTexParameteri(getTarget(), GL_TEXTURE_MIN_FILTER, filter);
+ glTexParameteri(getTarget(), GL_TEXTURE_MAG_FILTER, filter);
}
public void setWrap(int wrap) {
bind();
- glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);
+ glTexParameteri(getTarget(), GL_TEXTURE_WRAP_S, wrap);
+ glTexParameteri(getTarget(), GL_TEXTURE_WRAP_T, wrap);
}
public void bind() {
if (!valid())
throw new IllegalStateException("trying to bind a texture that was disposed");
- glBindTexture(target, id);
+ glBindTexture(getTarget(), id);
}
public void dispose() {
@@ -229,11 +252,11 @@ public boolean valid() {
return id!=0;
}
- public float getWidth() {
+ public int getWidth() {
return width;
}
- public float getHeight() {
+ public int getHeight() {
return height;
}
View
74 src/mdesl/graphics/TextureRegion.java
@@ -1,35 +1,25 @@
-/**
- * Copyright (c) 2012, Matt DesLauriers All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * * Redistributions in binary
- * form must reproduce the above copyright notice, this list of conditions and
- * the following disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * * Neither the name of the Matt DesLauriers nor the names
- * of his contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
+/*******************************************************************************
+ * Copyright 2011 See AUTHORS file.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
package mdesl.graphics;
+/** A trimmed down version of TextureRegion from LibGDX.
+ * Defines a rectangular area of a texture. The coordinate system used has its origin in the upper left corner with the x-axis
+ * pointing to the right and the y axis pointing downwards.
+ * @author mzechner
+ * @author Nathan Sweet */
public class TextureRegion implements ITexture {
protected Texture texture;
@@ -38,8 +28,8 @@
protected float u2;
protected float v2;
- protected float regionWidth;
- protected float regionHeight;
+ protected int regionWidth;
+ protected int regionHeight;
public TextureRegion(Texture texture) {
this(texture, 0, 0);
@@ -57,6 +47,10 @@ public TextureRegion(Texture texture, float u, float v, float u2, float v2) {
set(texture, u, v, u2, v2);
}
+ public TextureRegion(TextureRegion region, int x, int y, int width, int height) {
+ set(region, x, y, width, height);
+ }
+
public void set(Texture texture, int x, int y, int width, int height) {
set(texture, x / (float)texture.getWidth(),
y / (float)texture.getHeight(),
@@ -76,6 +70,18 @@ public void set(Texture texture, float u, float v, float u2, float v2) {
regionHeight = Math.round(Math.abs(v2 - v) * texture.getHeight());
}
+ public void set(TextureRegion region, int x, int y, int width, int height) {
+ set(region.texture, x + region.getRegionX(), y + region.getRegionY(), width, height);
+ }
+
+ public int getRegionX () {
+ return Math.round(u * texture.getWidth());
+ }
+
+ public int getRegionY () {
+ return Math.round(v * texture.getHeight());
+ }
+
public void flip (boolean x, boolean y) {
if (x) {
float temp = u;
@@ -164,7 +170,7 @@ public void setV2(float v2) {
* @return the width of this region
*/
@Override
- public float getWidth() {
+ public int getWidth() {
return regionWidth;
}
@@ -173,7 +179,7 @@ public float getWidth() {
* @return the height of this region
*/
@Override
- public float getHeight() {
+ public int getHeight() {
return regionHeight;
}
View
55 src/mdesl/graphics/text/BitmapFont.java
@@ -58,7 +58,7 @@
int descent;
int pages;
Glyph[] glyphs;
- Texture[] texturePages;
+ TextureRegion[] texturePages;
class Glyph {
int chr;
@@ -78,9 +78,9 @@ public int getKerning(int c) {
return kerning[c];
}
- void updateRegion(Texture tex) {
+ void updateRegion(TextureRegion tex) {
if (region==null)
- region = new TextureRegion(tex);
+ region = new TextureRegion(tex, 0, 0, tex.getWidth(), tex.getHeight());
region.set(tex, x, y, width, height);
}
}
@@ -90,22 +90,26 @@ public BitmapFont(URL fontDef, URL texture) throws IOException {
}
public BitmapFont(URL fontDef, Texture texture) throws IOException {
+ this(fontDef.openStream(), new TextureRegion(texture));
+ }
+
+ public BitmapFont(URL fontDef, TextureRegion texture) throws IOException {
this(fontDef.openStream(), texture);
}
- public BitmapFont(InputStream fontDef, Texture texture) throws IOException {
- this(fontDef, new Texture[] { texture });
+ public BitmapFont(InputStream fontDef, TextureRegion texture) throws IOException {
+ this(fontDef, new TextureRegion[] { texture });
}
- public BitmapFont(InputStream fontDef, Texture[] texturePages) throws IOException {
+ public BitmapFont(InputStream fontDef, TextureRegion[] texturePages) throws IOException {
this(fontDef, Charset.defaultCharset(), texturePages);
}
- public BitmapFont(InputStream fontDef, Charset charset, Texture[] texturePages) throws IOException {
+ public BitmapFont(InputStream fontDef, Charset charset, TextureRegion[] texturePages) throws IOException {
this.texturePages = texturePages;
parseFont(fontDef, charset);
}
-
+
public int getLineHeight() {
return lineHeight;
}
@@ -127,14 +131,45 @@ public void drawText(SpriteBatch batch, CharSequence text, int x, int y, int sta
if (lastGlyph!=null)
x += lastGlyph.getKerning(c);
- else
- x -= g.xoffset;
+
lastGlyph = g;
batch.draw(g.region, x + g.xoffset, y + g.yoffset, g.width, g.height);
x += g.xadvance;
}
}
+ public int getBaseline() {
+ return baseLine;
+ }
+
+ public int getWidth(CharSequence text) {
+ return getWidth(text, 0, text.length());
+ }
+
+ public int getWidth(CharSequence text, int start, int end) {
+ Glyph lastGlyph = null;
+ int width = 0;
+ for (int i=start; i<end; i++) {
+ char c = text.charAt(i);
+ //TODO: make unsupported glyphs a bit cleaner...
+ if (c > glyphs.length || c < 0)
+ continue;
+ Glyph g = glyphs[c];
+ if (g==null)
+ continue;
+
+ if (lastGlyph!=null)
+ width += lastGlyph.getKerning(c);
+
+ lastGlyph = g;
+// width += g.width + g.xoffset;
+
+// width += g.width + g.xoffset;
+ width += g.xadvance;
+ }
+ return width;
+ }
+
private static String parse(String line, String tag) {
tag += "=";
int start = line.indexOf(tag);
View
167 test/mdesl/test/FBOTest.java
@@ -0,0 +1,167 @@
+package mdesl.test;
+
+import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
+import static org.lwjgl.opengl.GL11.GL_ONE;
+import static org.lwjgl.opengl.GL11.*;
+import static org.lwjgl.opengl.GL11.GL_RGBA;
+import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA;
+import static org.lwjgl.opengl.GL11.glBlendFunc;
+import static org.lwjgl.opengl.GL11.glClear;
+import static org.lwjgl.opengl.GL11.glClearColor;
+import static org.lwjgl.opengl.GL14.glBlendFuncSeparate;
+import static org.lwjgl.opengl.GL30.GL_COLOR_ATTACHMENT0;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import javax.imageio.ImageIO;
+
+import mdesl.graphics.Color;
+import mdesl.graphics.Framebuffer;
+import mdesl.graphics.SpriteBatch;
+import mdesl.graphics.Texture;
+import mdesl.graphics.TextureRegion;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.GL11;
+
+public class FBOTest extends SimpleGame {
+
+ public static void main(String[] args) throws LWJGLException {
+ Game game = new FBOTest();
+ game.setDisplayMode(640, 480, false);
+ game.start();
+ }
+
+ final int FBO_SIZE = 512;
+
+ //our sprite batch
+ SpriteBatch batch;
+
+ Texture atlas;
+ TextureRegion track, thumb;
+
+ Framebuffer fbo;
+ TextureRegion fboRegion;
+
+ protected void create() throws LWJGLException {
+ super.create();
+ //create our font
+ try {
+ atlas = new Texture(Util.getResource("res/slider.png"), Texture.NEAREST);
+
+ //ideally you would use a texture packer like in LibGDX
+ track = new TextureRegion(atlas, 0, 0, 64, 256);
+ thumb = new TextureRegion(atlas, 65, 0, 64, 128);
+
+ int width = track.getWidth();
+ int height = track.getHeight();
+
+ //create a new FBO with the width and height of our track
+ if (Texture.isNPOTSupported()) {
+ fbo = new Framebuffer(width, height);
+ fboRegion = new TextureRegion(fbo.getTexture());
+ } else {
+ int texWidth = Texture.toPowerOfTwo(width);
+ int texHeight = Texture.toPowerOfTwo(height);
+ fbo = new Framebuffer(texWidth, texHeight);
+ fboRegion = new TextureRegion(fbo.getTexture(), 0, texHeight-height, width, height);
+ }
+ fboRegion.flip(false, true);
+ //GL uses lower left coords... we use upper-left for textures, so we need to flip Y
+
+ } catch (IOException e) {
+ throw new RuntimeException("couldn't decode textures");
+ }
+ batch = new SpriteBatch();
+
+ renderSlider();
+ }
+
+ protected void renderSlider() {
+ //make our offscreen FBO the current buffer
+ fbo.begin();
+
+ //we need to first clear our FBO with transparent black
+ glClearColor(0f,0f,0f,0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ //since our FBO is a different size than our Display,
+ //we need to resize our SpriteBatch in order for it to render correctly
+ System.out.println(fbo.getWidth()+" "+fbo.getTexture().getWidth());
+// batch.resize(Display.getWidth(), Display.getHeight());
+// batch.resize(fbo.getTexture().getWidth(), fbo.getTexture().getHeight());
+// batch.resize(fboRegion.getWidth(), fboRegion.getHeight());
+ batch.resize(fbo.getWidth(), fbo.getHeight());
+
+ //setup our alpha blending to avoid blending twice
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
+
+ //start our batch
+ batch.begin();
+
+ //render some sprites to our offscreen FBO
+ float x = 0;
+ float y = 0;
+ int val = 40; //example value amount
+
+ //draw sprites
+ batch.draw(track, x, y);
+ batch.draw(thumb, x, y + val);
+
+ //end (flush) our batch
+ batch.end();
+
+ //unbind the FBO
+ fbo.end();
+
+ //now we are back to screen aka "back buffer" rendering
+ //so we should resize our SpriteBatch to the Display size
+ batch.resize(Display.getWidth(), Display.getHeight());
+
+ //now let's re-set blending to the default...
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ protected void render() throws LWJGLException {
+ //nice smooth background color
+ float L = 233/255f;
+ glClearColor(L, L, L, 1f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ //we don't need super.render() since it just clears the screen, and we have that above
+
+ //whever the slider moves we will need to call renderSlider() to update the offscreen texture
+
+
+ //render the offscreen texture with "premultiplied alpha" blending
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ batch.begin();
+
+ //due to our different blend funcs we need to use RGBA to specify opacity
+ //tinting becomes unavailable with this solution
+ float a = .5f;
+ batch.setColor(a, a, a, a);
+
+ batch.draw(fboRegion, 0, 0);
+
+ batch.flush();
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ batch.draw(track, 200, 200);
+ batch.draw(thumb, 200, 250);
+
+ 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());
+ }
+}
View
133 test/mdesl/test/RectTest.java
@@ -0,0 +1,133 @@
+package mdesl.test;
+
+import static org.lwjgl.opengl.GL11.GL_RGBA;
+import static org.lwjgl.opengl.GL11.glClearColor;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import mdesl.graphics.Color;
+import mdesl.graphics.Framebuffer;
+import mdesl.graphics.SpriteBatch;
+import mdesl.graphics.Texture;
+import mdesl.graphics.TextureRegion;
+import mdesl.graphics.text.BitmapFont;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.Display;
+
+public class RectTest extends SimpleGame {
+
+ public static void main(String[] args) throws LWJGLException {
+ Game game = new RectTest();
+ game.setDisplayMode(640, 480, false);
+ game.start();
+ }
+
+ final int FBO_SIZE = 512;
+
+ //a simple font to play with
+ BitmapFont font;
+
+ //our sprite batch
+ SpriteBatch batch;
+
+ Texture fontTex;
+ TextureRegion rect;
+
+ Color dark = new Color(0x4e4e4e);
+ Color blue = new Color(0x96a2a5);
+ Color light = new Color(0xc9c9c9);
+
+ protected void create() throws LWJGLException {
+ super.create();
+ //create our font
+ try {
+ fontTex = new Texture(Util.getResource("res/ptsans_00.png"), Texture.NEAREST);
+
+ //in Photoshop, we included a small white box at the bottom right of our font sheet
+ //we will use this to draw lines and rectangles within the same batch as our text
+ rect = new TextureRegion(fontTex, fontTex.getWidth()-2, fontTex.getHeight()-2, 1, 1);
+
+ font = new BitmapFont(Util.getResource("res/ptsans.fnt"), fontTex);
+ } catch (IOException e) {
+ throw new RuntimeException("couldn't decode texture");
+ }
+
+ glClearColor(0.5f, .5f, .5f, 1f);
+ batch = new SpriteBatch();
+ }
+
+ void drawRect(int x, int y, int width, int height, int thickness) {
+ batch.draw(rect, x, y, width, thickness);
+ batch.draw(rect, x, y, thickness, height);
+ batch.draw(rect, x, y+height-thickness, width, thickness);
+ batch.draw(rect, x+width-thickness, y, thickness, height);
+ }
+
+ void drawLine(int x1, int y1, int x2, int y2, int thickness) {
+ int dx = x2-x1;
+ int dy = y2-y1;
+ float dist = (float)Math.sqrt(dx*dx + dy*dy);
+ float rad = (float)Math.atan2(dy, dx);
+ batch.draw(rect, x1, y1, dist, thickness, 0, 0, rad);
+ }
+
+
+ protected void render() throws LWJGLException {
+ super.render();
+
+ batch.begin();
+
+ int x = 25;
+ int y = 50;
+ int width = 250;
+ int height = font.getLineHeight() * 2;
+ batch.setColor(dark);
+ batch.draw(rect, x, y, width, height);
+ batch.setColor(blue);
+ batch.draw(rect, x+=2, y+=2, width-=4, height-=4);
+ batch.setColor(light);
+ batch.draw(rect, x+=5, y+=5, width-=10, height-=10);
+ batch.setColor(dark);
+
+ String str = "Hello world, muchos jalepe\u00f1o";
+
+ int fw = font.getWidth(str);
+ int fx = x + width/2 - fw/2;
+ int fy = y + height/2 - font.getLineHeight()/2;
+ int base = fy+font.getBaseline() + 1;
+ font.drawText(batch, str, fx, fy);
+
+ //underline only a portion of the string
+ fx += font.getWidth(str, 0, 6);
+ fw = font.getWidth(str, 6, 11);
+
+ //draw underline
+ drawLine(fx, base, fx + fw, base, 1);
+
+ //draw some other stuff
+ batch.setColor(Color.WHITE);
+
+ //test drawing a rectangle
+ drawRect(180, y + 50, 50, 25, 3);
+
+ //test drawing a rotated line
+ batch.draw(rect, x + width + 30, 25, 100, 1, 0, 0, (float)Math.toRadians(45));
+
+ //test drawing line from point A to point B
+ batch.setColor(Color.PINK);
+ drawLine(400, 300, Mouse.getX(), Display.getHeight()-Mouse.getY()-1, 3);
+
+ 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());
+ }
+}
View
8 test/mdesl/test/shadertut/ShaderLesson4.java
@@ -40,14 +40,14 @@ public static void main(String[] args) throws LWJGLException {
//our program
ShaderProgram program;
-
+
protected void create() throws LWJGLException {
super.create();
try {
- tex0 = new Texture(Util.getResource("res/grass.png"));
- tex1 = new Texture(Util.getResource("res/dirt.png"));
- mask = new Texture(Util.getResource("res/mask.png"));
+ tex0 = new Texture(Util.getResource("res/grass.png"), Texture.LINEAR, Texture.REPEAT);
+ tex1 = new Texture(Util.getResource("res/dirt.png"), Texture.LINEAR, Texture.REPEAT);
+ mask = new Texture(Util.getResource("res/mask.png"), Texture.LINEAR, Texture.REPEAT);
} catch (IOException e) {
throw new RuntimeException("couldn't decode textures");
}
View
122 test/mdesl/test/shadertut/ShaderLesson4B.java
@@ -0,0 +1,122 @@
+package mdesl.test.shadertut;
+
+import static org.lwjgl.opengl.GL11.glClearColor;
+import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
+import static org.lwjgl.opengl.GL13.GL_TEXTURE1;
+import static org.lwjgl.opengl.GL13.GL_TEXTURE2;
+import static org.lwjgl.opengl.GL13.glActiveTexture;
+
+import java.io.IOException;
+
+import mdesl.graphics.SpriteBatch;
+import mdesl.graphics.Texture;
+import mdesl.graphics.glutils.ShaderProgram;
+import mdesl.test.Game;
+import mdesl.test.SimpleGame;
+import mdesl.test.Util;
+
+import org.lwjgl.LWJGLException;
+import org.lwjgl.opengl.Display;
+
+public class ShaderLesson4B extends SimpleGame {
+
+ public static void main(String[] args) throws LWJGLException {
+ Game game = new ShaderLesson4B();
+ game.setDisplayMode(640, 480, false);
+ game.start();
+ }
+
+ //our grass texture
+ Texture tex0;
+
+ //our dirt texture
+ Texture tex1;
+
+ //our mask texture
+ Texture mask;
+
+ //our sprite batch
+ SpriteBatch batch;
+
+ //our program
+ ShaderProgram program;
+
+ //our very simple timing mechanism which we'll send to the shader
+ float tick = 0;
+
+ protected void create() throws LWJGLException {
+ super.create();
+
+ try {
+ tex0 = new Texture(Util.getResource("res/grass.png"), Texture.NEAREST, Texture.REPEAT);
+ tex1 = new Texture(Util.getResource("res/dirt.png"), Texture.NEAREST, Texture.REPEAT);
+ mask = new Texture(Util.getResource("res/mask.png"), Texture.NEAREST, Texture.REPEAT);
+ } catch (IOException e) {
+ throw new RuntimeException("couldn't decode textures");
+ }
+
+ //load our shader program and sprite batch
+ try {
+ final String VERTEX = Util.readFile(Util.getResourceAsStream("res/shadertut/lesson4.vert"));
+ final String FRAGMENT = Util.readFile(Util.getResourceAsStream("res/shadertut/lesson4b.frag"));
+
+ //create our shader program -- be sure to pass SpriteBatch's default attributes!
+ program = new ShaderProgram(VERTEX, FRAGMENT, SpriteBatch.ATTRIBUTES);
+
+ //Good idea to log any warnings if they exist
+ if (program.getLog().length()!=0)
+ System.out.println(program.getLog());
+
+ //bind our program
+ program.use();
+
+ //set our sampler2D uniforms
+ program.setUniformi("u_texture1", 1);
+ program.setUniformi("u_mask", 2);
+ program.setUniformf("time", tick);
+
+ //create our sprite batch
+ batch = new SpriteBatch(program);
+ } catch (Exception e) {
+ //simple exception handling...
+ e.printStackTrace();
+ System.exit(0);
+ }
+
+
+ //make GL_TEXTURE2 the active texture unit, then bind our mask texture
+ glActiveTexture(GL_TEXTURE2);
+ mask.bind();
+
+ //do the same for our other two texture units
+ glActiveTexture(GL_TEXTURE1);
+ tex1.bind();
+
+ glActiveTexture(GL_TEXTURE0);
+ tex0.bind();
+
+ //gray clear colour
+ glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
+ }
+
+ protected void render() throws LWJGLException {
+ super.render();
+
+ batch.begin();
+
+ //shader will be bound already
+ program.setUniformf("time", tick+=0.01f);
+
+ batch.draw(tex0, 10, 10);
+
+ 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());
+ }
+}
View
BIN test/res/mask.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN test/res/ptsans_00.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN test/res/ptsans_00_atlas.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
25 test/res/shadertut/hblur.frag
@@ -0,0 +1,25 @@
+#version 120
+
+uniform sampler2D tex0;
+uniform float resolution;
+uniform float radius;
+
+void main() {
+ vec4 sum = vec4(0.0);
+ vec2 tc = gl_TexCoord[0].st;
+ float blur = radius/resolution;
+
+ sum += texture2D(tex0, vec2(tc.x - 4.0*blur, tc.y)) * 0.05;
+ sum += texture2D(tex0, vec2(tc.x - 3.0*blur, tc.y)) * 0.09;
+ sum += texture2D(tex0, vec2(tc.x - 2.0*blur, tc.y)) * 0.12;
+ sum += texture2D(tex0, vec2(tc.x - 1.0*blur, tc.y)) * 0.15;
+
+ sum += texture2D(tex0, vec2(tc.x, tc.y)) * 0.16;
+
+ sum += texture2D(tex0, vec2(tc.x + 1.0*blur, tc.y)) * 0.15;
+ sum += texture2D(tex0, vec2(tc.x + 2.0*blur, tc.y)) * 0.12;
+ sum += texture2D(tex0, vec2(tc.x + 3.0*blur, tc.y)) * 0.09;
+ sum += texture2D(tex0, vec2(tc.x + 4.0*blur, tc.y)) * 0.05;
+
+ gl_FragColor = vec4(sum.rgba);
+}
View
99 test/res/shadertut/lesson4b.frag
@@ -0,0 +1,99 @@
+//"in" attributes from our vertex shader
+varying vec4 vColor;
+varying vec2 vTexCoord;
+
+//our different texture units
+uniform sampler2D u_texture; //default GL_TEXTURE0, expected by SpriteBatch
+uniform sampler2D u_texture1;
+uniform sampler2D u_mask;
+
+uniform float time;
+
+ /////////////////////////////////////////////////////////////////////////
+ /////////////////// SIMPLEX NOISE FROM WEBGL-NOISE //////////////////////
+ /////////////////////////////////////////////////////////////////////////
+ // https://github.com/ashima/webgl-noise/wiki //
+ /////////////////////////////////////////////////////////////////////////
+
+vec3 mod289(vec3 x) {
+ return x - floor(x * (1.0 / 289.0)) * 289.0;
+}
+
+vec2 mod289(vec2 x) {
+ return x - floor(x * (1.0 / 289.0)) * 289.0;
+}
+
+vec3 permute(vec3 x) {
+ return mod289(((x*34.0)+1.0)*x);
+}
+
+float snoise(vec2 v) {
+ const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0
+ 0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
+ -0.577350269189626, // -1.0 + 2.0 * C.x
+ 0.024390243902439); // 1.0 / 41.0
+// First corner
+ vec2 i = floor(v + dot(v, C.yy) );
+ vec2 x0 = v - i + dot(i, C.xx);
+
+// Other corners
+ vec2 i1;
+ //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0
+ //i1.y = 1.0 - i1.x;
+ i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
+ // x0 = x0 - 0.0 + 0.0 * C.xx ;
+ // x1 = x0 - i1 + 1.0 * C.xx ;
+ // x2 = x0 - 1.0 + 2.0 * C.xx ;
+ vec4 x12 = x0.xyxy + C.xxzz;
+ x12.xy -= i1;
+
+// Permutations
+ i = mod289(i); // Avoid truncation effects in permutation
+ vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
+ + i.x + vec3(0.0, i1.x, 1.0 ));
+
+ vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
+ m = m*m ;
+ m = m*m ;
+
+// Gradients: 41 points uniformly over a line, mapped onto a diamond.
+// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
+
+ vec3 x = 2.0 * fract(p * C.www) - 1.0;
+ vec3 h = abs(x) - 0.5;
+ vec3 ox = floor(x + 0.5);
+ vec3 a0 = x - ox;
+
+// Normalise gradients implicitly by scaling m
+// Approximation of: m *= inversesqrt( a0*a0 + h*h );
+ m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
+
+// Compute final noise value at P
+ vec3 g;
+ g.x = a0.x * x0.x + h.x * x0.y;
+ g.yz = a0.yz * x12.xz + h.yz * x12.yw;
+ return 130.0 * dot(m, g);
+}
+
+
+ /////////////////////////////////////////////////////////////////////////
+ //////////////////// END SIMPLEX NOISE ////////////////////////
+ /////////////////////////////////////////////////////////////////////////
+
+
+void main(void) {
+ //sample the colour from the first texture
+ vec4 texColor0 = texture2D(u_texture, vTexCoord);
+ //sample the colour from the second texture
+ vec4 texColor1 = texture2D(u_texture1, vTexCoord);
+
+ //pertube texcoord by x and y
+ vec2 distort = 0.2 * vec2(snoise(vTexCoord + vec2(0.0, time/3.0)),
+ snoise(vTexCoord + vec2(time/3.0, 0.0)) );
+
+ //get the mask; we will only use the alpha channel
+ float mask = texture2D(u_mask, vTexCoord + distort).a;
+
+ //interpolate the colours based on the mask
+ gl_FragColor = vColor * mix(texColor0, texColor1, mask);
+}
View
17 test/res/shadertut/lesson5.vert
@@ -0,0 +1,17 @@
+//combined projection and view matrix
+uniform mat4 u_projView;
+
+//"in" attributes from our SpriteBatch
+attribute vec2 Position;
+attribute vec2 TexCoord;
+attribute vec4 Color;
+
+//"out" varyings to our fragment shader
+varying vec4 vColor;
+varying vec2 vTexCoord;
+
+void main() {
+ vColor = Color;
+ vTexCoord = TexCoord;
+ gl_Position = u_projView * vec4(Position, 0.0, 1.0);
+}
View
27 test/res/shadertut/lesson5_horiz.frag
@@ -0,0 +1,27 @@
+//"in" attributes from our vertex shader
+varying vec4 vColor;
+varying vec2 vTexCoord;
+
+uniform sampler2D tex0;
+uniform float resolution;
+uniform float radius;
+
+void main() {
+ vec4 sum = vec4(0.0);
+ vec2 tc = vTexCoord;
+ float blur = radius/resolution;
+
+ sum += texture2D(tex0, vec2(tc.x - 4.0*blur, tc.y)) * 0.05;
+ sum += texture2D(tex0, vec2(tc.x - 3.0*blur, tc.y)) * 0.09;
+ sum += texture2D(tex0, vec2(tc.x - 2.0*blur, tc.y)) * 0.12;
+ sum += texture2D(tex0, vec2(tc.x - 1.0*blur, tc.y)) * 0.15;
+
+ sum += texture2D(tex0, vec2(tc.x, tc.y)) * 0.16;
+
+ sum += texture2D(tex0, vec2(tc.x + 1.0*blur, tc.y)) * 0.15;
+ sum += texture2D(tex0, vec2(tc.x + 2.0*blur, tc.y)) * 0.12;
+ sum += texture2D(tex0, vec2(tc.x + 3.0*blur, tc.y)) * 0.09;
+ sum += texture2D(tex0, vec2(tc.x + 4.0*blur, tc.y)) * 0.05;
+
+ gl_FragColor = vColor * sum;
+}
View
27 test/res/shadertut/lesson5_vert.frag
@@ -0,0 +1,27 @@
+//"in" attributes from our vertex shader
+varying vec4 vColor;
+varying vec2 vTexCoord;
+
+uniform sampler2D tex0;
+uniform float resolution;
+uniform float radius;
+
+void main() {
+ vec4 sum = vec4(0.0);
+ vec2 tc = vTexCoord;
+ float blur = radius/resolution;
+
+ sum += texture2D(tex0, vec2(tc.x, tc.y - 4.0*blur)) * 0.05;
+ sum += texture2D(tex0, vec2(tc.x, tc.y - 3.0*blur)) * 0.09;
+ sum += texture2D(tex0, vec2(tc.x, tc.y - 2.0*blur)) * 0.12;
+ sum += texture2D(tex0, vec2(tc.x, tc.y - 1.0*blur)) * 0.15;
+
+ sum += texture2D(tex0, vec2(tc.x, tc.y)) * 0.16;
+
+ sum += texture2D(tex0, vec2(tc.x, tc.y + 1.0*blur)) * 0.15;
+ sum += texture2D(tex0, vec2(tc.x, tc.y + 2.0*blur)) * 0.12;
+ sum += texture2D(tex0, vec2(tc.x, tc.y + 3.0*blur)) * 0.09;
+ sum += texture2D(tex0, vec2(tc.x, tc.y + 4.0*blur)) * 0.05;
+
+ gl_FragColor = vColor * sum;
+}
View
25 test/res/shadertut/vblur.frag
@@ -0,0 +1,25 @@
+#version 120
+
+uniform sampler2D tex0;
+uniform float resolution;
+uniform float radius;
+
+void main() {
+ vec4 sum = vec4(0.0);
+ vec2 tc = gl_TexCoord[0].st;
+ float blur = radius/resolution;
+
+ sum += texture2D(tex0, vec2(tc.x, tc.y - 4.0*blur)) * 0.05;
+ sum += texture2D(tex0, vec2(tc.x, tc.y - 3.0*blur)) * 0.09;
+ sum += texture2D(tex0, vec2(tc.x, tc.y - 2.0*blur)) * 0.12;
+ sum += texture2D(tex0, vec2(tc.x, tc.y - 1.0*blur)) * 0.15;
+
+ sum += texture2D(tex0, vec2(tc.x, tc.y)) * 0.16;
+
+ sum += texture2D(tex0, vec2(tc.x, tc.y + 1.0*blur)) * 0.15;
+ sum += texture2D(tex0, vec2(tc.x, tc.y + 2.0*blur)) * 0.12;
+ sum += texture2D(tex0, vec2(tc.x, tc.y + 3.0*blur)) * 0.09;
+ sum += texture2D(tex0, vec2(tc.x, tc.y + 4.0*blur)) * 0.05;
+
+ gl_FragColor = vec4(sum.rgba);
+}
View
BIN test/res/slider.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN test/res/slider_opaque.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 3feb67b

Please sign in to comment.
Something went wrong with that request. Please try again.