Skip to content

Commit

Permalink
add image wrapping example
Browse files Browse the repository at this point in the history
  • Loading branch information
eonarheim committed Apr 7, 2024
1 parent aa81c0f commit e9e3422
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 9 deletions.
13 changes: 13 additions & 0 deletions sandbox/tests/imagewrapping/index.html
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image Wrapping</title>
</head>
<body>
<canvas id="game"></canvas>
<script src="../../lib/excalibur.js"></script>
<script src="index.js"></script>
</body>
</html>
59 changes: 59 additions & 0 deletions sandbox/tests/imagewrapping/index.ts
@@ -0,0 +1,59 @@
/// <reference path="../../lib/excalibur.d.ts" />

// identity tagged template literal lights up glsl-literal vscode plugin
var glsl = x => x[0];
var game = new ex.Engine({
canvasElementId: 'game',
width: 800,
height: 800
});

var fireShader = glsl`#version 300 es
precision mediump float;
uniform float animation_speed;
uniform float offset;
uniform float u_time_ms;
uniform sampler2D u_graphic;
uniform sampler2D noise;
in vec2 v_uv;
out vec4 fragColor;
void main() {
vec2 animatedUV = vec2(v_uv.x, v_uv.y + (u_time_ms / 1000.) * 0.5);
vec4 color = texture(noise, animatedUV);
color.rgb += (v_uv.y - 0.5);
color.rgb = step(color.rgb, vec3(0.5));
color.rgb = vec3(1.0) - color.rgb;
fragColor.rgb = mix(vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 0.0), v_uv.y);
fragColor.a = color.r;
fragColor.rgb = fragColor.rgb * fragColor.a;
}
`

var noiseImage = new ex.ImageSource('./noise.png', {
filtering: ex.ImageFiltering.Blended,
wrapping: ex.ImageWrapping.Repeat
});

var material = game.graphicsContext.createMaterial({
name: 'fire',
fragmentSource: fireShader,
images: {
'noise': noiseImage
}
})

var actor = new ex.Actor({
pos: ex.vec(0, 200),
anchor: ex.vec(0, 0),
width: 800,
height: 600,
color: ex.Color.Red
});
actor.graphics.material = material;
game.add(actor);

var loader = new ex.Loader([noiseImage]);

game.start(loader);
Binary file added sandbox/tests/imagewrapping/noise.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 16 additions & 1 deletion src/engine/Graphics/Context/texture-loader.ts
Expand Up @@ -90,7 +90,22 @@ export class TextureLoader {
gl.bindTexture(gl.TEXTURE_2D, tex);

gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
const { x: xWrap, y: yWrap} = (wrapping ?? TextureLoader.wrapping);

let wrappingConfig: ImageWrapConfiguration;
if (wrapping) {
if (typeof wrapping === 'string') {
wrappingConfig = {
x: wrapping,
y: wrapping
};
} else {
wrappingConfig = {
x: wrapping.x,
y: wrapping.y
};
}
}
const { x: xWrap, y: yWrap} = (wrappingConfig ?? TextureLoader.wrapping);
switch (xWrap) {
case ImageWrapping.Clamp:
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
Expand Down
32 changes: 24 additions & 8 deletions src/engine/Graphics/ImageSource.ts
Expand Up @@ -9,10 +9,7 @@ import { ImageWrapping } from './Wrapping';

export interface ImageSourceOptions {
filtering?: ImageFiltering;
wrapping?: {
x: ImageWrapping,
y: ImageWrapping
};
wrapping?: ImageWrapConfiguration | ImageWrapping;
bustCache?: boolean;
}

Expand Down Expand Up @@ -92,15 +89,22 @@ export class ImageSource implements Loadable<HTMLImageElement> {
constructor(path: string, bustCacheOrOptions: boolean | ImageSourceOptions, filtering?: ImageFiltering) {
this.path = path;
let bustCache = false;
let wrapping: ImageWrapConfiguration;
let wrapping: ImageWrapConfiguration | ImageWrapping;
if (typeof bustCacheOrOptions === 'boolean') {
bustCache = bustCacheOrOptions;
} else {
({ filtering, wrapping, bustCache } = {...bustCacheOrOptions});
}
this._resource = new Resource(path, 'blob', bustCache);
this.filtering = filtering ?? this.filtering;
this.wrapping = wrapping ?? this.wrapping;
if (typeof wrapping === 'string') {
this.wrapping = {
x: wrapping,
y: wrapping
};
} else {
this.wrapping = wrapping ?? this.wrapping;
}
if (path.endsWith('.svg') || path.endsWith('.gif')) {
this._logger.warn(`Image type is not fully supported, you may have mixed results ${path}. Fully supported: jpg, bmp, and png`);
}
Expand All @@ -123,8 +127,20 @@ export class ImageSource implements Loadable<HTMLImageElement> {
}

if (options?.wrapping) {
imageSource.data.setAttribute(ImageSourceAttributeConstants.WrappingX, options?.wrapping.x);
imageSource.data.setAttribute(ImageSourceAttributeConstants.WrappingY, options?.wrapping.y);
let wrapping: ImageWrapConfiguration;
if (typeof options.wrapping === 'string') {
wrapping = {
x: options.wrapping,
y: options.wrapping
};
} else {
wrapping = {
x: options.wrapping.x,
y: options.wrapping.y
};
}
imageSource.data.setAttribute(ImageSourceAttributeConstants.WrappingX, wrapping.x);
imageSource.data.setAttribute(ImageSourceAttributeConstants.WrappingY, wrapping.y);
} else {
imageSource.data.setAttribute(ImageSourceAttributeConstants.WrappingX, ImageWrapping.Clamp);
imageSource.data.setAttribute(ImageSourceAttributeConstants.WrappingY, ImageWrapping.Clamp);
Expand Down

0 comments on commit e9e3422

Please sign in to comment.