WebGL - multiple shapes but only one is rendered instead of the others - webgl

I have to draw multiple shapes in a simple WebGL program and there occurs a problem which seems unplausible for me. If I try to draw only a single shape, everything works fine.
In the "main" function I create the following instances and render them
_coneInstance = new Cone();
_coneInstance.initCone();
_cylinderInstance = new Cylinder();
_cylinderInstance.initCylinder();
_sphereInstance = new Sphere();
_sphereInstance.initSphere();
renderAll();
This leads to the problem, that all three objets looks like shapes
In renderAll() the render function of each object is called - these functions are shown below.
This looks like, that all vertices from the cone and the cylinder are overwritten by the sphere.
Since each object drawn separately is correctly working, I will not post the vertex-building process.
function Cone()
{
...
this.vertexBuffer = 0;
this.initCone = function()
{
this.generateCone();
this.initBuffers();
}
this.generateCone = function()
{
...
}
this.initBuffers = function()
{
this.vertexBuffer = gl.createBuffer();
this.bind();
gl.bufferData(gl.ARRAY_BUFFER, flatten(this.triangleList), gl.STATIC_DRAW);
gl.enableVertexAttribArray(vPosition);
gl.vertexAttribPointer(vPosition, 4, gl.FLOAT, false, 0, 0);
this.unbind();
}
this.render = function()
{
this.bind();
gl.drawArrays(gl.TRIANGLE_FAN, 0, this.numTrianglesUpperPart);
gl.drawArrays(gl.TRIANGLE_FAN, this.numTrianglesUpperPart, this.numTrianglesLowerPart);
this.unbind();
}
this.bind = function()
{
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
console.log(gl.isBuffer(this.vertexBuffer ));
}
this.unbind = function()
{
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
}
function Cylinder()
{
...
this.vertexBuffer = 0;
this.initCylinder = function()
{
this.generateCylinder();
this.initCylinderBuffers();
}
this.generateCylinder = function()
{
...
}
this.initCylinderBuffers = function()
{
this.vertexBuffer = gl.createBuffer();
this.bind();
gl.bufferData(gl.ARRAY_BUFFER, flatten(this.cylinderVertexList), gl.STATIC_DRAW);
gl.enableVertexAttribArray(vPosition);
gl.vertexAttribPointer(vPosition, 4, gl.FLOAT, false, 0, 0);
this.unbind();
}
this.render = function()
{
this.bind();
gl.drawArrays(gl.TRIANGLE_FAN, 0, this.cylinderNumTrianglesUpperPart);
gl.drawArrays(gl.TRIANGLE_FAN, this.cylinderNumTrianglesUpperPart, this.cylinderNumTrianglesLowerPart);
gl.drawArrays(gl.TRIANGLES, this.cylinderNumTrianglesUpperPart+this.cylinderNumTrianglesLowerPart, this.cylinderNumTrianglesMiddlePart);
this.unbind();
}
this.bind = function()
{
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
console.log(gl.isBuffer(this.vertexBuffer ));
}
this.unbind = function()
{
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
}
function Sphere()
{
...
this.vertexBuffer = 0;
this.initSphere = function()
{
this.generateSphere();
this.initSphereBuffers();
}
this.generateSphere = function()
{
...
}
this.initSphereBuffers = function()
{
this.vertexBuffer = gl.createBuffer();
this.bind();
gl.bufferData(gl.ARRAY_BUFFER, flatten(this.unindexedVertices), gl.STATIC_DRAW);
gl.enableVertexAttribArray(vPosition);
gl.vertexAttribPointer(vPosition, 4, gl.FLOAT, false, 0, 0);
this.unbind();
}
this.render = function()
{
this.bind();
gl.drawArrays(gl.TRIANGLES, 0, this.numTriangles);
this.unbind();
}
this.bind = function()
{
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
console.log(gl.isBuffer(this.vertexBuffer ));
}
this.unbind = function()
{
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
}

You have to update the attribute pointers to the buffer every time.
When binding a vertex attribute pointer you're setting a global pointer to the buffer currently bound. Having a bound buffer is a prerequisite for that, but it does not store any state in regards to vertex attribute pointers. So you have to either move the pointer setup into your render method or use the OES_vertex_array_object extension.
Your initBuffers functions need to be split
This part is "initing" a buffer and only needs to happen at init time
this.vertexBuffer = gl.createBuffer();
this.bind();
gl.bufferData(gl.ARRAY_BUFFER, flatten(this.unindexedVertices), gl.STATIC_DRAW);
This part needs to happen every time before you render
this.bind();
gl.enableVertexAttribArray(vPosition);
gl.vertexAttribPointer(vPosition, 4, gl.FLOAT, false, 0, 0);

Related

Jspdf and html2pdf not working with dynamic data for multiple pages(more than 25 pages in pdf) , overlapping issue

I am trying to implement generic solution since my html content won't be fixed,i want to convert html 2 pdf but problem is getting cut between the pages, page break not working correctly.
//var staticHeight = 0;
//$('div').each(function () {
// staticHeight += $(this).filter(':visible').outerHeight(true);
// var pageHeight = 100
// console.log(staticHeight)
// if (staticHeight > pageHeight) {
// $(this).after('<div class="page-break" id="activediv2"> asasjjasasa asas </div>');
// staticHeight = 0;
// }
//});
//return html2canvas(document.getElementsByClassName('custom-content')[0], {
// onrendered: function (canvasObj) {
// startPrintProcess(canvasObj, 'printedPDF', function () {
// alert('PDF saved');
// });
// //save this object to the pdf
// }
//});
//return html2canvas($(element)[0], {
// background: "#ffffff",
// onrendered: function (canvas) {
// var myImage = canvas.toDataURL("image/jpeg,1.0");
// // Adjust width and height
// var imgWidth = (canvas.width * 60) / 247;
// var imgHeight = (canvas.height * 70) / 247;
// // jspdf changes
// var pdf = new jsPDF('l', 'mm', 'a4');
// pdf.addImage(myImage, 'png', 15, 2, imgWidth, imgHeight); // 2: 19
// pdf.save('sample.pdf');
// }
//});
var HTML_Width = $(element).width();
var HTML_Height = $(element).height();
var top_left_margin = 15;
var PDF_Width = HTML_Width + (top_left_margin * 2);
var PDF_Height = (PDF_Width * 1.5) + (top_left_margin * 2);
var canvas_image_width = HTML_Width;
var canvas_image_height = HTML_Height;
pdf = "";
html2canvas(element, {
background: '#FFFFFF',
onclone: function (doc) {
hiddenDiv = document.getElementsByClassName('custom-content')[0];
hiddenDiv.style.display = 'block';
},
onrendered: function (canvas) {
var width = canvas.width;
var height = canvas.height;
var millimeters = {};
millimeters.width = Math.floor(width * 0.274583);
millimeters.height = Math.floor(height * 0.274583);
var context = canvas.getContext('2d');
context.scale(2, 2);
var imgData = canvas.toDataURL('image/png');
var doc = new jsPDF("l", "mm", "a4");
// doc.deletePage(1);
// doc.addPage(millimeters.width, millimeters.height);
//doc.addImage(imgData, 'PNG', 0, 0, width, height);
//doc.save('wardrobemodel.pdf');
var totalPDFPages = Math.ceil(HTML_Height / PDF_Height) - 1;
for (var i = 0; i <= totalPDFPages; i++) {
doc.addPage(PDF_Width, PDF_Height);
doc.addImage(imgData, 'JPG', 0, -(PDF_Height * i) + (top_left_margin * 4), canvas_image_width, canvas_image_height);
}
doc.save('wardrobemodel.pdf');
}
});
//var worker = html2pdf().from(element).toPdf();
////for (let i = 0; i < pages.length; i++) {
//// worker = worker.set(opt).from(pages[i]).toContainer().toCanvas().toPdf().get('pdf').then((pdf) => {
//// if (i < pages.length - 1) { // Bump cursor ahead to new page until on last page
//// pdf.addPage();
//// }
//// });
////}
//worker = worker.save();
//$('.tile-body').find('div').each(function () {
// var eleHeight = $(this).filter(':visible').outerHeight(true);
// staticHeight += pix2mm(eleHeight, 300);
// var pageHeight = 257
// console.log(staticHeight)
// if (staticHeight > pageHeight) {
// $(this).after('<div class="page-break mt-1 mb-1" id="activediv2"></div>');
// staticHeight = 0;
// }
//});
return html2canvas(element, {
onrendered: function (canvasObj) {
startPrintProcess(canvasObj, 'printedPDF', function () {
alert('PDF saved');
});
//save this object to the pdf
}
});
//$('.tile-body').children('div').each(function () {
// var eleHeight = $(this).filter(':visible').outerHeight(true);
// staticHeight += pix2mm(eleHeight, 300);
// var pageHeight = 257
// console.log(staticHeight)
// if (staticHeight > pageHeight) {
// $(this).after('<div class="page-break mt-3 mb-5" id="activediv2"></div>');
// staticHeight = 0;
// }
//});
staticHeight = 0;
//var opt = {
// margin: 0.25,
// filename: 'ontract.pdf',
// image: { type: 'jpeg', quality: 0.98 },
// html2canvas: { scale: 2 },
// jsPDF: { unit: 'mm', format: 'a4', orientation: 'landscape' },
// pagebreak: { mode: 'avoid-all', after: '#activediv2' }
//};
//var worker = html2pdf().from(element).toPdf();
//worker.save();
// html2pdf().from(element).set(opt).toPdf().get('pdf').save()
// return;
//html2canvas(element, {
// logging: false
//}).then(function (canvas) {
// var pdf = new jsPDF('l', 'mm', 'a4');//A4 paper, portrait
// /// pdf.internal.scaleFactor = 30;
// var ctx = canvas.getContext('2d'),
// a4w = 190, a4h = 257,//A4 size, 210mm x 297mm, 10 mm margin on each side, display area 190x277
// imgHeight = Math.floor(a4h * canvas.width / a4w),//Convert pixel height of one page image to A4 display scale
// renderedHeight = 0;
// var pdfConf = {
// pagesplit: true,
// pagebreak: { mode: 'avoid-all', before: '#activediv2' }
// };
// var logo = document.getElementsByClassName(".logo-img")[0];//Icon placed in header
// while (renderedHeight < canvas.height) {
// var page = document.createElement("canvas");
// page.width = canvas.width;
// page.height = Math.min(imgHeight, canvas.height - renderedHeight);//Maybe less than one page
// //Trim the specified area with getImageData and draw it into the canvas object created earlier
// page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0);
// //Add an image to the page with a 10 mm / 20 mm margin
// pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 20, a4w, Math.min(a4h, a4w * page.height / page.width));
// //Add header logo
// // pdf.addImage(logo, 'SVG', 5, 3);
// var context = page.getContext('2d');
// context.scale(2, 2);
// //pdf.addHTML(element, { pagesplit: true, canvas: page }, function () {
// // // var out = pdf.output('dataurlnewwindow'); // crashed if bigger file
// // pdf.save('two-by-four.pdf')
// //});
// renderedHeight += imgHeight;
// if (renderedHeight < canvas.height)
// pdf.addPage();//Add an empty page if there is more to follow
// delete page;
// }
// pdf.save('content.pdf');
//});
//return;
//var HTML_Width = $(element).width();
//var HTML_Height = $(element).height();
//var top_left_margin = 15;
//var PDF_Width = HTML_Width + (top_left_margin * 2);
//var PDF_Height = (PDF_Width * 1.5) + (top_left_margin * 2);
//var canvas_image_width = HTML_Width;
//var canvas_image_height = HTML_Height;
//var totalPDFPages = Math.ceil(HTML_Height / PDF_Height) - 1;
//html2canvas($(element)[0], { allowTaint: true }).then(function (canvas) {
// var context = canvas.getContext('2d');
// context.scale(2, 2);
// console.log(canvas.height + " " + canvas.width);
// var imgData = canvas.toDataURL("image/jpeg", 1.0);
// var pdf = new jsPDF('l', 'pt', [PDF_Width, PDF_Height]);
// pdf.addImage(imgData, 'JPG', top_left_margin, top_left_margin, canvas_image_width, canvas_image_height);
// for (var i = 1; i <= totalPDFPages; i++) {
// pdf.addPage(PDF_Width, PDF_Height);
// pdf.addImage(imgData, 'JPG', top_left_margin, -(PDF_Height * i) + (top_left_margin * 4), canvas_image_width, canvas_image_height);
// }
// pdf.save("HTML-Document.pdf");
//});
//return;
///
//html2canvas($(element)[0], { allowTaint: true }).then(function (canvas) {
// calculatePDF_height_width(".print-wrap", 1);
// var imgData = canvas.toDataURL("image/png", 1.0);
// pdf.addPage(PDF_Width, PDF_Height);
// pdf.addImage(imgData, 'JPG', top_left_margin, top_left_margin, HTML_Width, HTML_Height);
// pdf.save("11.pdf")
//});
div {
page-break-inside: avoid;
}
this is what i tried
In short my target to achieve add page break if generated pdf is breaking html content between two pages.
I solve my problem for export HTML to multiple-page PDF. I create canvas per div. Perhaps this is will help you all.
private canvas: any = {
monthYearCanvas: null,
monthYearHeight: 0,
periodCanvas: null,
periodHeight: 0,
assetCanvas: null,
assetHeight: 0,
badActorCanvas: null,
badActorHeight: 0,
eventCanvas: null,
eventHeight: 0,
tenLowOffCanvas: null,
tenLowOffHeight: 0,
};
public triggerPrintReport(): void {
if (
this.isLoadingMonthYear ||
this.isLoadingOnPeriod ||
this.isLoadingOnAsset ||
this.isLoadingOnBadActor ||
this.isLoadingOnEvent ||
this.isLoadingTenLowOff
) {
alert('Wait for load data');
return;
}
this.messageReport = true;
const monthYearHTML = document.getElementById('htmlData-monthYear');
const periodHTML = document.getElementById('htmlData-period');
const assetHTML = document.getElementById('htmlData-asset');
const badActorHTML = document.getElementById('htmlData-badActor');
const eventHTML = document.getElementById('htmlData-event');
const tenLowOffHTML = document.getElementById('htmlData-tenLowOff');
this.createCanvasURL(monthYearHTML, 'monthYear');
this.createCanvasURL(periodHTML, 'period');
this.createCanvasURL(assetHTML, 'asset');
this.createCanvasURL(badActorHTML, 'badActor');
this.createCanvasURL(eventHTML, 'event');
this.createCanvasURL(tenLowOffHTML, 'tenLowOff');
}
private createCanvasURL(element: any, type: string): void {
html2canvas(element).then(canvas => {
const width = 208;
if (type === 'monthYear') {
this.canvas.monthYearHeight = canvas.height * width / canvas.width;
this.canvas.monthYearCanvas = canvas.toDataURL('image/png');
} else if (type === 'period') {
this.canvas.periodHeight = canvas.height * width / canvas.width;
this.canvas.periodCanvas = canvas.toDataURL('image/png');
} else if (type === 'asset') {
this.canvas.assetHeight = canvas.height * width / canvas.width;
this.canvas.assetCanvas = canvas.toDataURL('image/png');
} else if (type === 'badActor') {
this.canvas.badActorHeight = canvas.height * width / canvas.width;
this.canvas.badActorCanvas = canvas.toDataURL('image/png');
} else if (type === 'event') {
this.canvas.eventHeight = canvas.height * width / canvas.width;
this.canvas.eventCanvas = canvas.toDataURL('image/png');
} else if (type === 'tenLowOff') {
this.canvas.tenLowOffHeight = canvas.height * width / canvas.width;
this.canvas.tenLowOffCanvas = canvas.toDataURL('image/png');
}
this.exportPDF();
});
}
private exportPDF(): void {
const PDF = new jsPDF('p', 'mm', 'a4');
if (
this.canvas.monthYearCanvas &&
this.canvas.periodCanvas &&
this.canvas.assetCanvas &&
this.canvas.badActorCanvas &&
this.canvas.badActorCanvas &&
this.canvas.tenLowOffCanvas
) {
PDF.addImage(this.canvas.monthYearCanvas, 'PNG', 1, 10, 208, this.canvas.monthYearHeight);
PDF.addImage(this.canvas.periodCanvas, 'PNG', 1, 125, 208, this.canvas.periodHeight);
PDF.addPage();
PDF.addImage(this.canvas.assetCanvas, 'PNG', 1, 10, 208, this.canvas.assetHeight);
PDF.addPage();
PDF.addImage(this.canvas.badActorCanvas, 'PNG', 1, 10, 208, this.canvas.badActorHeight);
PDF.addPage();
PDF.addImage(this.canvas.eventCanvas, 'PNG', 1, 10, 208, this.canvas.eventHeight);
PDF.addPage('l');
PDF.addImage(this.canvas.tenLowOffCanvas, 'PNG', 1, 10, 208, this.canvas.tenLowOffHeight);
this.messageReport = false;
PDF.save('angular-demo.pdf');
}
}

copyteximage2D in terms of state machine

i dont know how copyteximage2D works,
i would like a explanation in term of the webgl state machine :
thanks to gman i have this :
gl = {
activeTextureUnit: 0,
textureUnits: [],
};
gl.activeTexture = function(unit) {
this.activeTextureUnit = unit - this.TEXTURE_0;
};
gl.bindTexture = function(bindPoint, texture) {
var textureUnit = this.textureUnits[this.activeTextureUnit];
switch (bindPoint) {
case this.TEXTURE_2D:
textureUnit.texture2D = texture;
break;
case ....
}
};
gl.copyTexImage2D = function( target, level, iformat, x, y, w,h,b) {
.....
..... gman please your code here thanks very much!!!
.....
}
copyTexImage2D copies from the current framebuffer or canvas into the given target of the current texture unit
gl = {
activeTextureUnit: 0,
textureUnits: [
{ gl.TEXTURE_2D: null, gl.TEXTURE_CUBE_MAP: null, ... },
{ gl.TEXTURE_2D: null, gl.TEXTURE_CUBE_MAP: null, ... },
{ gl.TEXTURE_2D: null, gl.TEXTURE_CUBE_MAP: null, ... },
{ gl.TEXTURE_2D: null, gl.TEXTURE_CUBE_MAP: null, ... },
...
],
framebufferBindPoints: {
gl.FRAMEBUFFER: gl.canvas.internalFramebuffer,
},
};
gl.bindFramebuffer = function(bindPoint, framebuffer) {
this.framebufferBindPoints[bindPoint] =
framebuffer ? framebuffer : gl.canvas.internalFramebuffer;
};
gl.copyTexImage2D = function( target, level, iformat, x, y, w,h,b) {
var textureUnit = this.textureUnits[this.activeTextureUnit];
var texture = textureUnit[target];
var framebuffer = this.framebufferBindPoints[gl.FRAMEBUFFER];
// copy from framebuffer into texture
}

Setting Schedule in Custom Layer and Callback Not Firing

I am working on a simple reusable custom Layer in Cocos2d-html5 to manage a classic continuous background scroller. I initially created this in my main game layer, where I got it working, but when I moved it to its own BackgroundScroller Layer everything works except that the Schedule, whether set from the Main Layer or in a method inside of BackgroundScroller the function "scroll" never gets called.
What can cause a schedule to be registered but not fire? Is it a scope issue? Should I schedule the event on the BackgroundScroller or from within the code that is instantiating it?
onEnter: function(){
var self = this;
this._super();
winSize = cc.director.getWinSize();
centerPos = cc.p(winSize.width/2, winSize.height/2);
bs = new BackgroundScroller("https://fbcdn-sphotos-f-a.akamaihd.net/hphotos-ak-xap1/v/t1.0-9/1014377_10153225997278888_209146662968373758_n.jpg?oh=287c045d5b8752581f8bdce968312c5c&oe=55BBA0B3&__gda__=1437658479_65b312f58967c3e1bd0ddb07260395cb",
winSize, centerPos, BackgroundScroller.Speeds.MEDIUM_SLOW);
this.addChild(bs);
bs.startScroll();
}
Here is the BackgrounScroller custom layer's code:
var BackgroundScroller = cc.Layer.extend( /** #lends cc.Layer# */ {
_bgSprites: [],
/* This is the interesting bit */
startScroll: function(scrollSpeed) {
scrollSpeed = scrollSpeed || this.scrollSpeed;
cc.log('Start Scroll:' + scrollSpeed);
this.schedule(this.scroll, scrollSpeed);
this.scheduleUpdate();
},
scroll: function(dt) {
debugger;
for (var i = 0; i < this._bgSprites.length; i++) {
var bgSprite = this._bgSprites[i];
bgSprite.setPositionX(bgSprite.getPosition().x - 1);
this.checkIsOffEdge(bgSprite);
}
},
ctor: function(bgSpriteOrCallbackFunction, winSize, centerPos, scrollSpeed) {
this._super();
this.scrollSpeed = scrollSpeed;
this.winSize = winSize || cc.director.getWinSize();
this.centerPos = centerPos || cc.p(this.winSize.width / 2, this.winSize.height / 2);
if (typeof bgSpriteOrCallbackFunction == "function") {
this.setupBackgroundSprite = bgSpriteOrCallbackFunction;
} else {
this.bgSpriteName = bgSpriteOrCallbackFunction;
}
this._bgSprites = [];
},
onEnter: function() {
this.setupBackgroundSprites();
},
stopScroll: function() {
this.pause();
},
/**
* Sets up sprites with either the Background sprite name or the callback function specified in the ctor.
* #returns void
*/
setupBackgroundSprites: function() {
cc.log("Setup background sprites");
this.totalBgWidth = 0;
var bgSpriteWidth = 0;
while (this.totalBgWidth < this.winSize.width * 2) {
var bgSprite = this.setupBackgroundSprite();
this._bgSprites.push(bgSprite);
bgSprite.setAnchorPoint(0, 0);
bgSpriteWidth = bgSprite.getBoundingBox().width;
this.addChild(bgSprite);
this.totalBgWidth += bgSpriteWidth;
this.maximumBgExtent = this.totalBgWidth - bgSpriteWidth;
var posN = (this._bgSprites.length - 1) * bgSprite.getBoundingBox().width; // Stack them left to right
bgSprite.setPositionX(posN);
}
cc.log("BgSprites in background sprites:" + this._bgSprites);
},
setupBackgroundSprite: function() {
var bgSprite = new cc.Sprite(this.bgSpriteName)
return bgSprite;
},
checkIsOffEdge: function(sprite) {
var spriteBB = sprite.getBoundingBox();
if (spriteBB.x + spriteBB.width < 0) {
sprite.setPositionX(this.maximumBgExtent - 1);
}
}
});
BackgroundScroller.Speeds = {
"SLOW": 0.5,
"MEDIUM_SLOW": 0.005,
"MEDIUM": 0.001,
"MEDIUM_FAST": 0.0005,
"FAST": 0.0001
};
I figured it out. I encapsulated everything but the schedule in the BackgroundScroller layer. In MainLayer I set the schedule and it calls "scroll" on the BackgroundScroller.
I'm still not sure why it wasn't working, but this makes sense--the parent layer is where all of this logic should be managed anyway.

Simple WebGL Program, RotateTriangle(WebGL Programming Guide, chapter3), Fail to Work

I'm Sorry to paste a list of code, but it's very simple.I don't know why, not warnings no errors, it breaks down in silence.Here is the source code, it refer to a utils.js file, I promise there is no errors in the outer file. Because other programs base on that work pretty well.
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<style>
body { background: pink }
canvas { background: orange }
</style>
<script src="utils.js"></script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec4 aVertexPosition;
uniform float uCosB, uSinB;
void main() {
gl_Position.x = aVertexPosition.x * uCosB - aVertexPosition.y * uSinB;
gl_Position.y = aVertexPosition.x * uCosB + aVertexPosition.y * uSinB;
gl_Position.z = aVertexPosition.z;
gl_Position.w = 1.0;
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
</script>
<script>
var gl, canvas, shaderProgram;
window.onload = function() {
initCanvasAndGL("canvas");
initProgram();
initBuffer();
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
var angle = 90 / 180 * Math.PI;
var uSinB = gl.getUniformLocation(shaderProgram, "uSinB");
var uCosB = gl.getUniformLocation(shaderProgram, "uCosB");
gl.uniform1f(uSinB, Math.sin(angle));
gl.uniform1f(uCosB, Math.cos(angle));
gl.drawArrays(gl.TRIANGLES, 0, 3);
}
function initBuffer() {
var vertices = [0.0, 0.5, -0.5, -0.5, 0.5, -0.5];
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
var aVertexPosition = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.vertexAttribPointer(aVertexPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aVertexPosition);
}
</script>
</head>
<body>
<canvas id="canvas" width="400" height="400">
Canvas Not Supported! :(
</canvas>
</body>
If you do suspect the utils.js, Here is the source code.
function initCanvasAndGL(canvasID) {
canvas = document.getElementById(canvasID);
var names = [
"webgl", "experimental-webgl",
"webkit-3d", "moz-webgl"
];
for(var i = 0; i < names.length; ++i) {
try {
gl = canvas.getContext(names[i]);
} catch(e) {}
if(gl) {
break;
}
}
if(!gl) {
alert("WebGL is not available! :(");
}
}
function getShader(gl, id) {
var shaderScript = document.getElementById(id);
if(!shaderScript) {
return null;
}
var str = "";
var k = shaderScript.firstChild;
while(k) {
if(k.nodeType == 3) {
str += k.textContent;
}
k = k.nextSibling;
}
var shader;
if(shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else if(shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
function initProgram() {
var vertexShader = getShader(gl, "shader-vs");
var fragmentShader = getShader(gl, "shader-fs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders! :(");
}
gl.useProgram(shaderProgram);
}
You can put it together to run the program. But the result really makes me crazy.
yes as the other person commented - you need to change your gl_Position.y as
gl_Position.y = aVertexPosition.x * uSinB + aVertexPosition.y * uCosB;
then you get a red triangle displayed
enjoy

File.browseForSave() on ipad

I'm porting AIR app to iOS. App saves document localy with File.browseForSave(). That seem not to to work on iPad. How is it possible to save files on iPad?
P.S. tracing File.url says "app-storage:/New%20map.comap". Maybe names with % are not allowed on iOS?
Best wishes
You can only save to specific directories within the apps sandboxed area. e.g. Documents directory.
Something like this saves an image to the documents directory. It uses the Adobe JPGEncoder to create a byte array that is written and the crop method to take a snapshot of the stage.
private function createImages():void {
var snapShot:Bitmap = crop(0, 0, 1024, 768);
f = File.documentsDirectory.resolvePath("test.jpg");
var stream:FileStream = new FileStream();
stream.open(f, FileMode.WRITE);
var j:JPGEncoder = new JPGEncoder(80);
var bytes:ByteArray = new ByteArray();
bytes = j.encode(snapShot.bitmapData);
stream.writeBytes(bytes, 0, bytes.bytesAvailable);
stream.close();
stream.openAsync(f, FileMode.READ);
stream.addEventListener(Event.COMPLETE, imagewritten, false, 0, true);
}
private function imagewritten(e:Event):void {
trace("done");
}
private function crop( _x:Number, _y:Number, _width:Number, _height:Number, displayObject:DisplayObject = null):Bitmap
{
var cropArea:Rectangle = new Rectangle( 0, 0, _width, _height );
var croppedBitmap = new Bitmap( new BitmapData( _width, _height ), PixelSnapping.ALWAYS, true );
croppedBitmap.bitmapData.draw( (displayObject!=null) ? displayObject : stage, new Matrix(1, 0, 0, 1, -_x, -_y) , null, null, cropArea, true );
cropArea = null;
return croppedBitmap;
}

Resources