Skip to content

Commit

Permalink
Adds Image rendering support. Fixes a bug in WebGL that would cause l…
Browse files Browse the repository at this point in the history
…ayers to be rendered out of order.
  • Loading branch information
Lios committed Apr 9, 2014
1 parent 6b3a575 commit 7adc386
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 23 deletions.
14 changes: 12 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,16 @@
});

Lynx.CM.Load("MouseEvents","KeyboardEvents");

Lynx.AM.QueueImage("logo","samples/snow/assets/logo.png");

Lynx.AM.LoadQueue(function(){
var logoE = new Lynx.E(Lynx.AM.Get("logo").Asset);
logoE.X = Viewport.Width / 2 - logoE.Width / 2;
logoE.Y = Viewport.Height /2 - logoE.Height /2;
Lynx.Scene.AddLayer();
Lynx.Scene.AddEntity(logoE);
});
});
}, false);

Expand All @@ -207,7 +217,7 @@

this.X += this.vx * Lynx.Main.Delta / 100;
this.Y += this.vy * Lynx.Main.Delta / 100;

if(this.X+this.Width > Viewport.Width + size)
{
this.X = 0;
Expand Down Expand Up @@ -251,7 +261,7 @@
e.Color = colors[Math.floor(Math.random() * colors.length)];

e.On("Update", updateElement);
Lynx.Scene.AddEntity(e);
Lynx.Scene.Layers[0].AddEntity(e);
}
</script>
<script src="src/Lynx.js">
Expand Down
10 changes: 8 additions & 2 deletions src/core/Entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ Lynx.Entity = function(pImage)
{
Lynx.Warning("A ghost entity has been created, please make sure to initialize all entities to avoid conflicts.");
}
else if(pImage instanceof Image)
else if(pImage[0] instanceof Image)
{

width = pImage[0].width;
height = pImage[0].height;
}
else if(Object.prototype.toString.call(pImage) == '[object Arguments]')
{
Expand All @@ -50,6 +51,9 @@ Lynx.Entity = function(pImage)
var canvasElement = new Lynx.CE(x, y, width, height, "entity");
var bounds = new Lynx.Rect(x, y, width, height);

if(pImage[0] instanceof Image)
canvasElement.Texture = pImage[0];

Object.defineProperty(that, "CanvasElement", {
get: function()
{
Expand All @@ -76,6 +80,8 @@ Lynx.Entity = function(pImage)
},
set: function(pX)
{
if(isNaN(pX))
return;
x = pX;
bounds.X = pX;
canvasElement.X = pX;
Expand Down
1 change: 1 addition & 0 deletions src/core/Layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Lynx.Layer = function(pParent, pIndex)
that.AddEntity = function(pEntity)
{
pEntity.Parent = this;
pEntity.CanvasElement.Layer = this.Index;
entities.push(pEntity);
};

Expand Down
36 changes: 33 additions & 3 deletions src/gfx/CanvasElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@ Lynx.CanvasElement = function(pX, pY, pWidth, pHeight, pElementType){
G: -1,
B: -1
};
var objectTexture = null;

that.X = pX;
that.Y = pY;
that.Width = pWidth;
that.Height = pHeight;
that.Type = pElementType;
that.Layer = 0;

/**
* Description: A property for the objects color. Returns -1 if not set.
* Description: A property for the objects color.
*
* @this {Lynx.CanvasElement}
* @param {HTMLCanvasElement} <pBuffer> Canvas buffer to draw upon
*/
Object.defineProperty(that, "Color", {
get: function()
Expand All @@ -53,6 +54,32 @@ Lynx.CanvasElement = function(pX, pY, pWidth, pHeight, pElementType){
Lynx.Warning("Could not set color of object to "+ pValue + " as it is not a whole, positive integer.");
}
});

/**
* Description: A property for the objects texture. Returns false if not set.
*
* @this {Lynx.CanvasElement}
*/
Object.defineProperty(that, "Texture", {
get: function()
{
if(!objectTexture)
return false;

return objectTexture;
},
set: function(pImage)
{
if(pImage instanceof Image || pImage instanceof WebGLTexture)
{
objectTexture = pImage;
}
else
{
Lynx.Log(typeof pImage);
}
}
})

/**
* Description: Draws the object to the canvas with a provided 2d Context.
Expand All @@ -63,7 +90,10 @@ Lynx.CanvasElement = function(pX, pY, pWidth, pHeight, pElementType){
*/
that.Draw = (function(context)
{
context.fillRect(this.X, this.Y, this.Width, this.Height);
if(objectTexture instanceof Image)
context.drawImage(objectTexture, this.X, this.Y, this.Width, this.Height);
else
context.fillRect(this.X, this.Y, this.Width, this.Height);
return true;
}).bind(that);

Expand Down
108 changes: 96 additions & 12 deletions src/gfx/Renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,15 @@ Lynx.Renderer = function(pCanvas){
*/
that.SortMethod = function(pA, pB)
{
//Sort by layer
if(pA.Layer > pB.Layer)
return 1;
else if(pA.Layer < pB.Layer)
return -1;

if(pA.Color.Hex == pB.Color.Hex)
return 0;
if(pA.Color.Hex > pB.Color.Hex)
else if(pA.Color.Hex > pB.Color.Hex)
return 1;

return -1;
Expand Down Expand Up @@ -89,8 +95,8 @@ Lynx.Renderer = function(pCanvas){

if(lastFillColor != pObject[i].Color)
{
if(pObject[i].Color)
var newColor = "#"+pObject[i].Color.toString(16);
if(pObject[i].Color.Hex != -1)
var newColor = "#"+pObject[i].Color.Hex.toString(16);
ctx.fillStyle = newColor;

lastFillColor = pObject[i].Color;
Expand Down Expand Up @@ -123,7 +129,10 @@ Lynx.Renderer = function(pCanvas){
fragmentShader = null;
var lastShaderColor = null;
var hasContext = false;

var blankTexture = null;
var texCoordBuffer = null,
positionBuffer = null;

var ready = false;

/**
Expand All @@ -135,12 +144,18 @@ Lynx.Renderer = function(pCanvas){
{
gl = context;
gl.viewport(0, 0, that.Parent.Width, that.Parent.Height);

//Clear current programs and shaders.
that.LoadShader("vs-default", function(pName){
that.LoadShader("fs-default", function(pSecName){
program = that.CompileProgram(that.CompileShader(pName), that.CompileShader(pSecName));

if(!program)
{
Lynx.Error("Failed to compile WebGL Program.");
return false;
}

gl.useProgram(program);

vertexShader = Lynx.Shaders.Get(pName);
Expand All @@ -149,12 +164,29 @@ Lynx.Renderer = function(pCanvas){
vertexShader.GetLocations(gl, program);
fragmentShader.GetLocations(gl, program);

gl.uniform2f(vertexShader.GetVariable("resolution").Location, this.Parent.Width, this.Parent.Height);
var texCoordLocation = vertexShader.GetVariable("texCoord", "attribute");

texCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.enableVertexAttribArray(texCoordLocation);
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);

blankTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, blankTexture);

buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.enableVertexAttribArray(vertexShader.GetVariable("position").Location);
gl.vertexAttribPointer(vertexShader.GetVariable("position").Location, 2, gl.FLOAT, false, 0, 0);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 255, 255, 255]));

gl.uniform2f(vertexShader.GetVariable("resolution", "uniform").Location, this.Parent.Width, this.Parent.Height);

positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.enableVertexAttribArray(vertexShader.GetVariable("position", "attribute").Location);
gl.vertexAttribPointer(vertexShader.GetVariable("position", "attribute").Location, 2, gl.FLOAT, false, 0, 0);

Lynx.Log("Finished loading shaders...");
});
Expand Down Expand Up @@ -289,6 +321,8 @@ Lynx.Renderer = function(pCanvas){

pObject.sort(this.SortMethod);

var lastLayer = 0;

for(var i = 0; i < pObject.length; i++)
{
if(pObject[i].Render)
Expand All @@ -297,6 +331,47 @@ Lynx.Renderer = function(pCanvas){
continue;
}

if(pObject[i].Layer != lastLayer)
{
renderBatch(buildArray);
buildArray = [];
}

if(pObject[i].Color.Hex == -1 && pObject[i].Texture !== false)
{
if(pObject[i].Texture instanceof Image)
{
var tempText = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tempText);

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, pObject[i].Texture);

pObject[i].Texture = tempText;
}

var texCoordLocation = vertexShader.GetVariable("texCoord", "attribute").Location;
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.enableVertexAttribArray(texCoordLocation);
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0.0, 0.0,
0.0, 1.0,
1.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 0.0]), gl.STATIC_DRAW);
gl.bindTexture(gl.TEXTURE_2D, pObject[i].Texture);

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(vertexShader.GetVariable("position", "attribute").Location, 2, gl.FLOAT, false, 0, 0);
}

if(pObject[i].Color.Hex != lastShaderColor)
{
renderBatch(buildArray);
Expand All @@ -305,7 +380,16 @@ Lynx.Renderer = function(pCanvas){
if(pObject[i].Color.Hex != -1)
{
var c = pObject[i].Color;
gl.uniform4f(fragmentShader.GetVariable("color").Location, c.R, c.G, c.B, 1.0);
gl.uniform4f(fragmentShader.GetVariable("color", "uniform").Location, c.R, c.G, c.B, 1.0);
if(lastShaderColor == -1)
{
gl.bindTexture(gl.TEXTURE_2D, blankTexture);
gl.disableVertexAttribArray(vertexShader.GetVariable("texCoord", "attribute").Location);
}
}
else
{
gl.uniform4f(fragmentShader.GetVariable("color", "uniform").Location, 1.0, 1.0, 1.0, 1.0);
}

lastShaderColor = pObject[i].Color.Hex;
Expand Down Expand Up @@ -336,7 +420,7 @@ Lynx.Renderer = function(pCanvas){
function renderBatch(pBuildArray)
{
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pBuildArray), gl.STATIC_DRAW);
gl.drawArrays(gl.TRIANGLES, 0, pBuildArray.length/2);
gl.drawArrays(gl.TRIANGLES, 0, pBuildArray.length/2);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/gfx/ShaderComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ Lynx.ShaderComponent = function(pName, pType, pBuildFunc)
* @param {string} <pName> The name of the variable to get
* @return {this.Variable{}|bool} the variable object or false if not found.
*/
that.GetVariable = function(pName)
that.GetVariable = function(pName, pType)
{
for(var i = 0; i < variables.length; i++)
{
if(variables[i].Name == pName)
if(variables[i].Name == pName && variables[i].DataType.toUpperCase() == pType.toUpperCase())
return variables[i];
}

Expand Down
6 changes: 5 additions & 1 deletion src/shaders/fs-default.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@
]).join("\n");
})();
this.Uniform("vec4", "color");
this.Uniform("sampler2D", "image");
this.Varying("vec2", "texCoord");

this.Main = function(){
var mainFunc = ([
"gl_FragColor = u_color;",
"gl_FragColor = texture2D(u_image, v_texCoord.st) * u_color;",
"if(gl_FragColor.a == 0.0)",
" discard;"
]).join("\n");
return mainFunc;
};
Expand Down
7 changes: 6 additions & 1 deletion src/shaders/vs-default.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
(function(){
new Lynx.ShaderComponent("vs-default", "vertex", function(){
this.Attribute("vec2","position");
this.Attribute("vec2", "texCoord");
this.Uniform("vec2", "resolution");
this.Varying("vec2", "texCoord");

this.Main = function(){
return "gl_Position = vec4((a_position / u_resolution * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0);";
return ([
"v_texCoord = a_texCoord;",
"gl_Position = vec4((a_position / u_resolution * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0);"
]).join("\n");
};
});
})();

0 comments on commit 7adc386

Please sign in to comment.