Moving Shape via Mouse in Opengl - animation

void Rectangle(void) {
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_QUADS);
glColor3f(1.0,0.0,0.0);
glVertex2f(m_x-0.25,m_y-0.25);
glColor3f(1.0,0.0,0.0);
glVertex2f(m_x-0.25,m_y-0.75);
glColor3f(1.0,0.0,0.0);
glVertex2f(m_x-0.75,m_y-0.75);
glColor3f(1.0,0.0,0.0);
glVertex2f(m_x-0.75,m_y-0.25);
glEnd();
glutSwapBuffers();
I want to move the rectangle to where pressed mouse. m_x and m_y are global variable.This function has called in main glutDisplayFunc(Rectangle), mouse function like this:
void mouse(int button,int state,int x,int y)
switch(button)
{
case GLUT_LEFT_BUTTON:
if(state==GLUT_DOWN)
{
m_x=x;
m_y=y;
Rectangle();
glutSwapBuffers();
}
break;
default:
break;
}
When the application runs ,it draws a rectangle after i pressed mouse the rectangle lost.What is my wrong?

Don't render stuff in your mouse handler like that, just update the object position and queue a redraw with glutPostRedisplay():
#include <GL/glut.h>
float objX = 100;
float objY = 100;
float objSize = 50;
bool dragging = false;
void mouse( int button, int state, int x, int y )
{
if( GLUT_DOWN == state )
{
bool colliding =
objX - objSize <= x && x <= objX + objSize
&&
objY - objSize <= y && y <= objY + objSize;
if( colliding )
{
dragging = true;
objX = x;
objY = y;
glutPostRedisplay();
}
}
else
{
dragging = false;
}
}
void motion( int x, int y )
{
if( dragging )
{
objX = x;
objY = y;
glutPostRedisplay();
}
}
void drawRect( float x, float y, float size )
{
glPushMatrix();
glTranslatef( x, y, 0.0f );
glScalef( size, size, 1.0f );
glBegin( GL_QUADS );
glColor3ub( 255, 255, 255 );
glVertex2f( -1, -1 );
glVertex2f( 1, -1 );
glVertex2f( 1, 1 );
glVertex2f( -1, 1 );
glEnd();
glPopMatrix();
}
void display()
{
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
const double w = glutGet( GLUT_WINDOW_WIDTH );
const double h = glutGet( GLUT_WINDOW_HEIGHT );
glOrtho( 0, w, h, 0, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
drawRect( objX, objY, objSize );
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 600, 600 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutMouseFunc( mouse );
glutMotionFunc( motion );
glutMainLoop();
return 0;
}

Related

How to write titles and legends in 2D fashion when working in P3D?

I have completed my sketch in working in P3D mode apart from titles and legends. How do I write these texts normally like 2D when working from this mode. I've introduced a camera in the sketch to enable panning and zooming functionality. This causes the titles to transform according to the camera. I've tried transforming the title to correct position but it still looks somewhat off
Also how can I make it free from mouse zoom and panning. ie it holds its position even though other parts of the sketch moves.
Here is my code:
PImage worldMap;
PShape box;
Table table;
int rowCount;
float x1, y1, z1, x2, y2, z2;
//Interaction Zoom and Pan Variables:
float zoom = 600;
float panLeft = 0;
float panTop = 0;
void setup() {
size(1400, 800, P3D);
table = new Table("From_USA_Coordinates.tsv");
rowCount = table.getRowCount();
worldMap = loadImage("world.topo.bathy.200406.3x5400x2700.jpg");
worldMap.resize(500, 300);
textureMode(NORMAL);
fill(255);
//stroke(color(44,48,32));
box = createShape(BOX, -650, 300, 0);
box.beginShape(BOX);
box.endShape();
box.setTexture(worldMap);
}
void draw() {
background(255);
fill(0);
titlesAndLegends();
display();
}
void mouseDragged() {
if((mouseX- pmouseX) > 0){
panLeft -= 5;
} else {
panLeft += 5;
}
if((mouseY-pmouseY) > 0) {
//panTop -=5;
}
}
void mouseWheel(MouseEvent event) {
float e = event.getCount();
if(e == 1) {
zoom += 30;
}else {
zoom -= 30;
}
}
public void display() {
camera(panLeft, zoom , zoom, panLeft, 0, panTop, 0, 1, 0); // eye(0, 600, 600) center(0, 0, 0) up(0, 1, 0)
pushMatrix();
translate(-350, 0, 0);
shape(box);
//box.scale(zoom);
popMatrix();
pushMatrix();
translate(350, 0, 0);
shape(box);
popMatrix();
pushMatrix();
// To use the center of the left box as center coordinates
translate(-350, 0, 0);
textSize(15);
for(int row = 1; row < rowCount; row++) {
float USALatitude = table.getFloat(row, 3);
float USALongitude = table.getFloat(row, 4);
String countryName = table.getString(row,1);
//Mapped Within X-axis of the left side map box
float mappedLatitude = map(USALatitude,-90, 90, 150, -150); // Latitude is in Y axis
float mappedLongitude = map(USALongitude, -180, 180, -325, 325); // Longitude in X Axis
x1 = mappedLongitude;
y1 = mappedLatitude;
z1 = 0;
float tripCountryLatitude = table.getFloat(row, 5);
float tripCountryLongitude = table.getFloat(row, 6);
float tripLatitude = map(tripCountryLatitude, -90, 90, 150, -150); // In Y, same mapping
float tripLongitude = map(tripCountryLongitude, -180, 180, 375, 1025);
// In X, having the position of the right box depending on the coordinates center
x2 = tripLongitude;
y2 = tripLatitude;
z2 = 0;
float zOff = map(0, 0, height, 300, 0); // Move mouse up and down
float a = (x2-x1)/3;
float b = (y2-y1)/3;
stroke(#F05252);
noFill();
bezier(x1, y1, z1, // First point
x1 + a, y1 + b, z1 + zOff, // First intermediate point
x2 - a, y2 - b, z2 + zOff, // Second intermediate point
x2, y2, z2);
//rotate(PI);
stroke(255);
fill(255);
text(countryName, x2-10, y2+10, z2+20);
}
popMatrix();
}
void titlesAndLegends() {
pushMatrix();
translate(-1000, -900, 0);
//rotateY(-PI/4);
textSize(50);
fill(0);
text("From USA to Other Parts of the World - 2019", width/2, 50);
popMatrix();
}
Code for table:
class Table {
int rowCount;
String[][] data;
Table(String filename) {
String[] rows = loadStrings(filename);
data = new String[rows.length][];
for (int i = 0; i < rows.length; i++) {
if (trim(rows[i]).length() == 0) {
continue; // skip empty rows
}
if (rows[i].startsWith("#")) {
continue; // skip comment lines
}
// split the row on the tabs
String[] pieces = split(rows[i], TAB);
// copy to the table array
data[rowCount] = pieces;
rowCount++;
// this could be done in one fell swoop via:
//data[rowCount++] = split(rows[i], TAB);
}
// resize the 'data' array as necessary
data = (String[][]) subset(data, 0, rowCount);
}
int getRowCount() {
return rowCount;
}
// find a row by its name, returns -1 if no row found
int getRowIndex(String name) {
for (int i = 0; i < rowCount; i++) {
if (data[i][0].equals(name)) {
return i;
}
}
println("No row named '" + name + "' was found");
return -1;
}
String getRowName(int row) {
return getString(row, 0);
}
String getString(int rowIndex, int column) {
return data[rowIndex][column];
}
String getString(String rowName, int column) {
return getString(getRowIndex(rowName), column);
}
int getInt(String rowName, int column) {
return parseInt(getString(rowName, column));
}
int getInt(int rowIndex, int column) {
return parseInt(getString(rowIndex, column));
}
float getFloat(String rowName, int column) {
return parseFloat(getString(rowName, column));
}
float getFloat(int rowIndex, int column) {
return parseFloat(getString(rowIndex, column));
}
void setRowName(int row, String what) {
data[row][0] = what;
}
void setString(int rowIndex, int column, String what) {
data[rowIndex][column] = what;
}
void setString(String rowName, int column, String what) {
int rowIndex = getRowIndex(rowName);
data[rowIndex][column] = what;
}
void setInt(int rowIndex, int column, int what) {
data[rowIndex][column] = str(what);
}
void setInt(String rowName, int column, int what) {
int rowIndex = getRowIndex(rowName);
data[rowIndex][column] = str(what);
}
void setFloat(int rowIndex, int column, float what) {
data[rowIndex][column] = str(what);
}
void setFloat(String rowName, int column, float what) {
int rowIndex = getRowIndex(rowName);
data[rowIndex][column] = str(what);
}
}
The links to my image files and datatable
https://drive.google.com/file/d/1sZw5Gc3xf_RTM_Ti6FeJ-_PVj49b0mlT/view
https://drive.google.com/file/d/111Tmhy6YDBQBmI2AaJuTPrrtdGZZpJSy/view
You should be able to isolate coordinate systems using pushMatrix()/popMatrix() calls. See the 2D Transformations tutorial as the same principle applies in 3D.
In your particular case it looks like display() is responsible for the 3D view.
You might want to isolate the camera() call into it's own coordinate system so it doesn't affect the legend:
public void display() {
// begin isolate camera transformed coordinate system
pushMatrix();
camera(panLeft, zoom , zoom, panLeft, 0, panTop, 0, 1, 0); // eye(0, 600, 600) center(0, 0, 0) up(0, 1, 0)
pushMatrix();
translate(-350, 0, 0);
shape(box);
//box.scale(zoom);
popMatrix();
pushMatrix();
translate(350, 0, 0);
shape(box);
popMatrix();
pushMatrix();
// To use the center of the left box as center coordinates
translate(-350, 0, 0);
textSize(15);
for(int row = 1; row < rowCount; row++) {
float USALatitude = table.getFloat(row, 3);
float USALongitude = table.getFloat(row, 4);
String countryName = table.getString(row,1);
//Mapped Within X-axis of the left side map box
float mappedLatitude = map(USALatitude,-90, 90, 150, -150); // Latitude is in Y axis
float mappedLongitude = map(USALongitude, -180, 180, -325, 325); // Longitude in X Axis
x1 = mappedLongitude;
y1 = mappedLatitude;
z1 = 0;
float tripCountryLatitude = table.getFloat(row, 5);
float tripCountryLongitude = table.getFloat(row, 6);
float tripLatitude = map(tripCountryLatitude, -90, 90, 150, -150); // In Y, same mapping
float tripLongitude = map(tripCountryLongitude, -180, 180, 375, 1025);
// In X, having the position of the right box depending on the coordinates center
x2 = tripLongitude;
y2 = tripLatitude;
z2 = 0;
float zOff = map(0, 0, height, 300, 0); // Move mouse up and down
float a = (x2-x1)/3;
float b = (y2-y1)/3;
stroke(#F05252);
noFill();
bezier(x1, y1, z1, // First point
x1 + a, y1 + b, z1 + zOff, // First intermediate point
x2 - a, y2 - b, z2 + zOff, // Second intermediate point
x2, y2, z2);
//rotate(PI);
stroke(255);
fill(255);
text(countryName, x2-10, y2+10, z2+20);
}
popMatrix();
// end isolate camera
popMatrix();
}
As an illustration, here's a modifider version of the camera() example, printing the transformation matrix before and after transformations:
size(100, 100, P3D);
noFill();
background(204);
// reset all transformations
resetMatrix();
println("before camera");
printMatrix();
pushMatrix();
camera(70.0, 35.0, 120.0, 50.0, 50.0, 0.0,
0.0, 1.0, 0.0);
println("after camera");
printMatrix();
translate(50, 50, 0);
rotateX(-PI/6);
rotateY(PI/3);
noFill();
box(45);
popMatrix();
// back to no transformations
printMatrix();
fill(0);
text("text2D",-50,-40,-100);

OpenGL ES 2.0 - Fisheye shader displays a grey image

I've been trying to use a fisheye shader from Shadertoy.
I've added my own frame resolution, and changed some keywords (texture -> texture2D, fragColor -> gl_FragColor) but that's it.
I don't really know why it doesn't work and how to debug it..
As a result I get a unicolor grey image.
Here's the code of my fragment shader :
precision mediump float;
uniform vec4 v_Color;
uniform sampler2D u_Texture;
varying vec2 v_TexCoordinate;
#define RESOLUTION_WIDTH 375.0
#define RESOLUTION_HEIGHT 211.0
#define POWER 2.0
void main() {
vec2 fragCoord = v_TexCoordinate;
vec2 iResolution = vec2(RESOLUTION_WIDTH, RESOLUTION_HEIGHT);
vec2 p = fragCoord.xy / iResolution.x; // normalized coords with some cheat
float prop = iResolution.x / iResolution.y;
vec2 m = vec2(0.5, 0.5 / prop); // center coords
vec2 d = p - m; // vector from center to current fragment
float r = sqrt(dot(d, d)); // distance of pixel from center
float power = POWER;
float bind; // radius of 1:1 effect
if (power > 0.0)
bind = sqrt(dot(m, m)); // stick to corners
else {
if (prop < 1.0)
bind = m.x;
else
bind = m.y;
} // stick to borders
// Weird formulas
vec2 uv;
if (power > 0.0) // fisheye
uv = m + normalize(d) * tan(r * power) * bind / tan( bind * power);
else if (power < 0.0) // antifisheye
uv = m + normalize(d) * atan(r * -power * 10.0) * bind / atan(-power * bind * 10.0);
else uv = p; // no effect for power = 1.0
vec3 col = texture2D(u_Texture, vec2(uv.x, -uv.y * prop)).xyz; // Second part of cheat
gl_FragColor = vec4(col, 1.0);
}
Here's my original shader to display an image that works perfectly :
precision mediump float;
uniform vec4 v_Color;
uniform sampler2D u_Texture;
varying vec2 v_TexCoordinate;
void main() {
// premultiplied alpha
vec4 texColor = texture2D(u_Texture, v_TexCoordinate);
// Scale the texture RGB by the vertex color
texColor.rgb *= v_Color.rgb;
// Scale the texture RGBA by the vertex alpha to reinstate premultiplication
gl_FragColor = texColor * v_Color.a;
}
Here's the link to the expected result on ShaderToy :
ShaderToy fisheye
Original result image :
With my shader :
With Rabbid76 solution :
With power = 1.1 :
With solution n2 and power = 10 (bigger image to see better) :
There's some background behind the text, don't pay attention to it ;)
In your shader code fragCoord is assumed to be a window coordinate, were the minimum is (0, 0) and the maximum is the width and height of the viewport. But in your code v_TexCoordinate is assigned to fragCoord. v_TexCoordinate is the texture corodiante in range [0, 1].
Use gl_FragCoord instead of v_TexCoordinate:
// vec2 fragCoord = v_TexCoordinate; <--- delete
vec2 fragCoord = gl_FragCoord.xy;
vec2 p = fragCoord.xy / iResolution.x;
Or skip dividing by the window resolution:
vec2 fragCoord = v_TexCoordinate;
// vec2 p = fragCoord.xy / iResolution.x; <-- delete
vec2 p = fragCoord.xy * vec2(1.0, iResolution.y/iResolution.x);
If the aspect ratio correction is not needed, then it can be even done:
vec2 p = v_TexCoordinate.xy;
See the WebGL example, where I use your original shader code and applied the suggested changes:
(function loadscene() {
var gl, canvas, prog, bufObj = {};
var texture;
function render(deltaMS) {
texture.bound = texture.bound || texture.bind( 0 );
gl.viewport( 0, 0, vp_size[0], vp_size[1] );
gl.enable( gl.DEPTH_TEST );
gl.clearColor( 0.0, 0.0, 0.0, 1.0 );
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
ShProg.Use( progDraw );
ShProg.SetF2( progDraw, "resolution", vp_size );
ShProg.SetI1( progDraw, "u_texture", 0 );
VertexBuffer.Draw( bufRect );
requestAnimationFrame(render);
}
function initScene() {
canvas = document.getElementById( "texture-canvas");
gl = canvas.getContext( "experimental-webgl" );
//gl = canvas.getContext( "webgl2" );
if ( !gl )
return;
progDraw = ShProg.Create(
[ { source : "draw-shader-vs", stage : gl.VERTEX_SHADER },
{ source : "draw-shader-fs", stage : gl.FRAGMENT_SHADER }
] );
progDraw.inPos = gl.getAttribLocation( progDraw.progObj, "inPos" );
if ( progDraw.progObj == 0 )
return;
bufRect = VertexBuffer.Create(
[ { data : [ -1, -1, 1, -1, 1, 1, -1, 1 ], attrSize : 2, attrLoc : progDraw.inPos } ],
[ 0, 1, 2, 0, 2, 3 ] );
texture = new Texture( "https://raw.githubusercontent.com/Rabbid76/graphics-snippets/master/resource/texture/supermario.jpg" );
texture.bound = false;
window.onresize = resize;
resize();
requestAnimationFrame(render);
}
function resize() {
//vp_size = [gl.drawingBufferWidth, gl.drawingBufferHeight];
vp_size = [window.innerWidth, window.innerHeight]
vp_size[0] = vp_size[1] = Math.min(vp_size[0], vp_size[1]);
//vp_size = [256, 256]
canvas.width = vp_size[0];
canvas.height = vp_size[1];
}
var ShProg = {
Create: function (shaderList) {
var shaderObjs = [];
for (var i_sh = 0; i_sh < shaderList.length; ++i_sh) {
var shderObj = this.Compile(shaderList[i_sh].source, shaderList[i_sh].stage);
if (shderObj) shaderObjs.push(shderObj);
}
var prog = {}
prog.progObj = this.Link(shaderObjs)
if (prog.progObj) {
prog.attrInx = {};
var noOfAttributes = gl.getProgramParameter(prog.progObj, gl.ACTIVE_ATTRIBUTES);
for (var i_n = 0; i_n < noOfAttributes; ++i_n) {
var name = gl.getActiveAttrib(prog.progObj, i_n).name;
prog.attrInx[name] = gl.getAttribLocation(prog.progObj, name);
}
prog.uniLoc = {};
var noOfUniforms = gl.getProgramParameter(prog.progObj, gl.ACTIVE_UNIFORMS);
for (var i_n = 0; i_n < noOfUniforms; ++i_n) {
var name = gl.getActiveUniform(prog.progObj, i_n).name;
prog.uniLoc[name] = gl.getUniformLocation(prog.progObj, name);
}
}
return prog;
},
AttrI: function (prog, name) { return prog.attrInx[name]; },
UniformL: function (prog, name) { return prog.uniLoc[name]; },
Use: function (prog) { gl.useProgram(prog.progObj); },
SetI1: function (prog, name, val) { if (prog.uniLoc[name]) gl.uniform1i(prog.uniLoc[name], val); },
SetF1: function (prog, name, val) { if (prog.uniLoc[name]) gl.uniform1f(prog.uniLoc[name], val); },
SetF2: function (prog, name, arr) { if (prog.uniLoc[name]) gl.uniform2fv(prog.uniLoc[name], arr); },
SetF3: function (prog, name, arr) { if (prog.uniLoc[name]) gl.uniform3fv(prog.uniLoc[name], arr); },
SetF4: function (prog, name, arr) { if (prog.uniLoc[name]) gl.uniform4fv(prog.uniLoc[name], arr); },
SetM33: function (prog, name, mat) { if (prog.uniLoc[name]) gl.uniformMatrix3fv(prog.uniLoc[name], false, mat); },
SetM44: function (prog, name, mat) { if (prog.uniLoc[name]) gl.uniformMatrix4fv(prog.uniLoc[name], false, mat); },
Compile: function (source, shaderStage) {
var shaderScript = document.getElementById(source);
if (shaderScript)
source = shaderScript.text;
var shaderObj = gl.createShader(shaderStage);
gl.shaderSource(shaderObj, source);
gl.compileShader(shaderObj);
var status = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS);
if (!status) alert(gl.getShaderInfoLog(shaderObj));
return status ? shaderObj : null;
},
Link: function (shaderObjs) {
var prog = gl.createProgram();
for (var i_sh = 0; i_sh < shaderObjs.length; ++i_sh)
gl.attachShader(prog, shaderObjs[i_sh]);
gl.linkProgram(prog);
status = gl.getProgramParameter(prog, gl.LINK_STATUS);
if ( !status ) alert(gl.getProgramInfoLog(prog));
return status ? prog : null;
} };
var VertexBuffer = {
Create: function(attribs, indices, type) {
var buffer = { buf: [], attr: [], inx: gl.createBuffer(), inxLen: indices.length, primitive_type: type ? type : gl.TRIANGLES };
for (var i=0; i<attribs.length; ++i) {
buffer.buf.push(gl.createBuffer());
buffer.attr.push({ size : attribs[i].attrSize, loc : attribs[i].attrLoc, no_of: attribs[i].data.length/attribs[i].attrSize });
gl.bindBuffer(gl.ARRAY_BUFFER, buffer.buf[i]);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array( attribs[i].data ), gl.STATIC_DRAW);
}
gl.bindBuffer(gl.ARRAY_BUFFER, null);
if ( buffer.inxLen > 0 ) {
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.inx);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( indices ), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}
return buffer;
},
Draw: function(bufObj) {
for (var i=0; i<bufObj.buf.length; ++i) {
gl.bindBuffer(gl.ARRAY_BUFFER, bufObj.buf[i]);
gl.vertexAttribPointer(bufObj.attr[i].loc, bufObj.attr[i].size, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray( bufObj.attr[i].loc);
}
if ( bufObj.inxLen > 0 ) {
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufObj.inx);
gl.drawElements(bufObj.primitive_type, bufObj.inxLen, gl.UNSIGNED_SHORT, 0);
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
}
else
gl.drawArrays(bufObj.primitive_type, 0, bufObj.attr[0].no_of );
for (var i=0; i<bufObj.buf.length; ++i)
gl.disableVertexAttribArray(bufObj.attr[i].loc);
gl.bindBuffer( gl.ARRAY_BUFFER, null );
} };
class Texture {
constructor( name, dflt ) {
let texture = this;
this.dflt = dflt || [128,128,128,255]
let image = { "cx": this.dflt.w || 1, "cy": this.dflt.h || 1, "plane": this.dflt.p || this.dflt };
this.size = [image.cx, image.cy];
this.dummyObj = Texture.createTexture2D( image, true )
this.image = new Image(64,64);
this.image.setAttribute('crossorigin', 'anonymous');
this.image.onload = function () {
let cx = 1 << 31 - Math.clz32(texture.image.naturalWidth);
if ( cx < texture.image.naturalWidth ) cx *= 2;
let cy = 1 << 31 - Math.clz32(texture.image.naturalHeight);
if ( cy < texture.image.naturalHeight ) cy *= 2;
var canvas = document.createElement( 'canvas' );
canvas.width = cx;
canvas.height = cy;
var context = canvas.getContext( '2d' );
context.drawImage( texture.image, 0, 0, canvas.width, canvas.height );
texture.textureObj = Texture.createTexture2D( canvas, true );
texture.size = [cx, cy];
}
this.image.src = name;
}
static createTexture2D( image, flipY ) {
let t = gl.createTexture();
gl.activeTexture( gl.TEXTURE0 );
gl.bindTexture( gl.TEXTURE_2D, t );
gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, flipY != undefined && flipY == true );
if ( image.cx && image.cy && image.plane )
gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, image.cx, image.cy, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(image.plane) );
else
gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT );
gl.bindTexture( gl.TEXTURE_2D, null );
return t;
}
bind( texUnit = 0 ) {
gl.activeTexture( gl.TEXTURE0 + texUnit );
if ( this.textureObj ) {
gl.bindTexture( gl.TEXTURE_2D, this.textureObj );
return true;
}
gl.bindTexture( gl.TEXTURE_2D, this.dummyObj );
return false;
}
};
initScene();
})();
<script id="draw-shader-vs" type="x-shader/x-vertex">
precision mediump float;
attribute vec2 inPos;
void main()
{
gl_Position = vec4( inPos.xy, 0.0, 1.0 );
}
</script>
<script id="draw-shader-fs" type="x-shader/x-fragment">
precision mediump float;
uniform vec2 resolution;
uniform sampler2D u_Texture;
#define RESOLUTION_WIDTH 375.0
#define RESOLUTION_HEIGHT 211.0
#define POWER 2.0
void main( void )
{
vec2 fragCoord = gl_FragCoord.xy;
vec2 iResolution = resolution;
//vec2 fragCoord = v_TexCoordinate;
//vec2 iResolution = vec2(RESOLUTION_WIDTH, RESOLUTION_HEIGHT);
vec2 p = fragCoord.xy / iResolution.x; // normalized coords with some cheat
float prop = iResolution.x / iResolution.y;
vec2 m = vec2(0.5, 0.5 / prop); // center coords
vec2 d = p - m; // vector from center to current fragment
float r = sqrt(dot(d, d)); // distance of pixel from center
float power = POWER;
float bind; // radius of 1:1 effect
if (power > 0.0)
bind = sqrt(dot(m, m)); // stick to corners
else {
if (prop < 1.0)
bind = m.x;
else
bind = m.y;
} // stick to borders
// Weird formulas
vec2 uv;
if (power > 0.0) // fisheye
uv = m + normalize(d) * tan(r * power) * bind / tan( bind * power);
else if (power < 0.0) // antifisheye
uv = m + normalize(d) * atan(r * -power * 10.0) * bind / atan(-power * bind * 10.0);
else uv = p; // no effect for power = 1.0
vec3 col = texture2D(u_Texture, vec2(uv.x, -uv.y * prop)).xyz; // Second part of cheat
gl_FragColor = vec4(col, 1.0);
}
</script>
<body>
<canvas id="texture-canvas" style="border: none"></canvas>
</body>

OpenGL 3.3 (mac) Error validating program: Validation Failed: No vertex array object bound

The following code compiles and runs without errors on linux but gives error
"Error validating program: 'Validation Failed: No vertex array object bound."
on mac OS 10.14.2 (Mojave). Note that the program compiles successfully but has a problem during runtime.
MacBook Pro (Retina, 15-inch, Mid 2015)
I am compiling using g++ -std=c++11 test.cpp -w -framework OpenGL -lglfw -lGLEW -o p
test.cpp
#include <bits/stdc++.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
#define cout(a) cout<<a<<endl
// IDs
GLuint VAO, VBO, VAO2, VBO2, shaderID, uniformModel;
float scale = 1.0, x = 0.0, y = 0.0;
const int numPoints = 50000;
const char* vShader = "shader.vert";
const char* fShader = "shader.frag";
void createSierpinskiGasket()
{
GLfloat points[3 * numPoints];
GLfloat vertices[] = {
-1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f
};
points[0] = 0.25f; points[1] = 0.50f; points[2] = 0.0f;
for(int i = 3; i < numPoints * 3; i += 3)
{
int j = rand() % 3;
points[i] = (points[i - 3] + vertices[j * 3]) / 2.0;
points[i + 1] = (points[i - 2] + vertices[j * 3 + 1]) / 2.0;
points[i + 2] = (points[i - 1] + vertices[j * 3 + 2]) / 2.0;
}
glGenVertexArrays(1, &VAO2);
glBindVertexArray(VAO2);
glGenBuffers(1, &VBO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void createTriangle()
{
GLfloat vertices[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
glGenVertexArrays(1, &VAO);
// Subsequent code will be associated with this VAO
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
// GL_ARRAY_BUFFER = Vertex data
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// GL_STATIC_DRAW = Not going to change the data (transforms are OK)
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Location, number, type, normalize, stride, offset
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
// Enable location 0
glEnableVertexAttribArray(0);
// Unbinding
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void addShader(const char* shaderIDCode, GLenum shaderIDType)
{
GLuint theShader = glCreateShader(shaderIDType);
const GLchar* theCode[1];
theCode[0] = shaderIDCode;
GLint codeLength[1];
codeLength[0] = strlen(shaderIDCode);
glShaderSource(theShader, 1, theCode, codeLength);
glCompileShader(theShader);
GLint result = 0;
GLchar eLog[1024] = { 0 };
glGetShaderiv(theShader, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetShaderInfoLog(theShader, sizeof(eLog), NULL, eLog);
printf("Error compiling the %d shaderID: '%s'\n", shaderIDType, eLog);
return;
}
glAttachShader(shaderID, theShader);
}
void compileShader(const char* vertexCode, const char* fragmentCode)
{
// Creating shaderID program
shaderID = glCreateProgram();
if(!shaderID)
{
cout("Error creating shaderID.");
return;
}
addShader(vertexCode, GL_VERTEX_SHADER);
addShader(fragmentCode, GL_FRAGMENT_SHADER);
GLint result = 0;
GLchar eLog[1024] = { 0 };
glLinkProgram(shaderID);
glGetProgramiv(shaderID, GL_LINK_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shaderID, sizeof(eLog), NULL, eLog);
printf("Error linking program: '%s'\n", eLog);
return;
}
glValidateProgram(shaderID);
glGetProgramiv(shaderID, GL_VALIDATE_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shaderID, sizeof(eLog), NULL, eLog);
printf("Error validating program: '%s'\n", eLog);
return;
}
}
string readFile(const char* fileLocation)
{
string content;
ifstream fileStream(fileLocation, ios::in);
if (!fileStream.is_open()) {
printf("Failed to read %s! File doesn't exist.", fileLocation);
return "";
}
string line = "";
while (!fileStream.eof())
{
getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
void createShader(const char* vertexLocation, const char* fragmentLocation)
{
string vertexString = readFile(vertexLocation);
string fragmentString = readFile(fragmentLocation);
const char* vertexCode = vertexString.c_str();
const char* fragmentCode = fragmentString.c_str();
compileShader(vertexCode, fragmentCode);
}
void handleKeys(GLFWwindow* window, int key, int code, int action, int mode)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
}
if (key == GLFW_KEY_EQUAL && action == GLFW_PRESS)
{
scale += 0.05;
}
if (key == GLFW_KEY_MINUS && action == GLFW_PRESS)
{
scale -= 0.05;
}
if (key == GLFW_KEY_LEFT && action == GLFW_PRESS)
{
x -= 0.05;
}
if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS)
{
x += 0.05;
}
if (key == GLFW_KEY_UP && action == GLFW_PRESS)
{
y += 0.05;
}
if (key == GLFW_KEY_DOWN && action == GLFW_PRESS)
{
y -= 0.05;
}
}
int main(void)
{
const GLint WIDTH = 800, HEIGHT = 600;
// Initializing GLFW
if(!glfwInit())
{
cout("GLFW initialization failed.");
glfwTerminate();
return 1;
}
// Setup GLFW window properties
// OpenGL version
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// Not backwards compatible
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Allow forward compatibility
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
GLFWwindow* mainWindow = glfwCreateWindow(WIDTH, HEIGHT, "Test Window", NULL, NULL);
if(!mainWindow)
{
cout("GLFW window creation failed.");
glfwTerminate();
return 1;
}
// Get buffer size information
int bufferWidth, bufferHeight;
glfwGetFramebufferSize(mainWindow, &bufferWidth, &bufferHeight);
// Set context for GLEW to use
glfwMakeContextCurrent(mainWindow);
// Allow modern extension features
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK)
{
cout("GLEW initialization failed.");
glfwDestroyWindow(mainWindow);
glfwTerminate();
return 1;
}
// Setup viewport size
glViewport(0, 0, bufferWidth, bufferHeight);
createTriangle();
createShader(vShader, fShader);
createSierpinskiGasket();
uniformModel = glGetUniformLocation(shaderID, "model");
// Loop until window is closed
while(!glfwWindowShouldClose(mainWindow))
{
// Get and handle user input
glfwPollEvents();
glfwSetKeyCallback(mainWindow, handleKeys);
// Clear window
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Clear colour buffer before next frame
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderID);
glm::mat4 model = glm::mat4();
model = glm::translate(model, glm::vec3(x, y, 0));
//model = glm::rotate(model, rotX * toRadians, glm::vec3(1, 0, 0));
//model = glm::rotate(model, rotY * toRadians, glm::vec3(0, 1, 0));
//model = glm::rotate(model, rotZ * toRadians, glm::vec3(0, 0, 1));
model = glm::scale(model, glm::vec3(scale, scale, scale));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
/*glBindVertexArray(VAO2);
glDrawArrays(GL_POINTS, 0, numPoints);
glBindVertexArray(0);*/
glUseProgram(0);
glfwSwapBuffers(mainWindow);
}
return 0;
}
shader.frag
#version 330
in vec4 vCol;
uniform mat4 model;
out vec4 color;
void main()
{
//color = vec4(1.0f, 1.0f, 0.0f, 1.0f);
color = vec4(vCol.x, vCol.y, 0.5, 1.0);
}
shader.vert
#version 330
layout (location = 0) in vec3 pos;
uniform mat4 model;
out vec4 vCol;
void main()
{
gl_Position = model * vec4(pos.x, pos.y, pos.z, 1.0f);
vCol = vec4(clamp(pos, 0.0f, 1.0f), 1.0f);
}
The message
Validation Failed: No vertex array object bound.
means that the validation of the program could not be performed, because no Vertex Array Object is bound, when glValidateProgram is called
See OpenGL 4.6 API Core Profile Specification; 11.1. VERTEX SHADERS; page 402
[...] As a development aid, use the command
void ValidateProgram( uint program );
to validate the program object program against the current GL state.
This means that the VAO which is should be drawn, by the shader program, has to be bound, before glValidateProgram is called.
Bind the "triangle" VAO, before the shader program is validated:
createTriangle();
glBindVertexArray(VAO);
createShader(vShader, fShader);

Cannot get OpenGL ES2 to display anything

I'm trying to draw a red rectangle using 2 triangles. I can clear the screen but I cannot get my triangles to render. What am I doing wrong?
Solid.vert shader:
#ifndef STRINGIFY
#define STRINGIFY(a) #a
#endif
char *vsSolid = STRINGIFY(
uniform mat4 Projection;
uniform mat4 ModelView;
attribute vec4 vPosition;
void main()
{
gl_Position = Projection * ModelView * vPosition;
}
);
Solid.frag shader:
#ifndef STRINGIFY
#define STRINGIFY(a) #a
#endif
char *fsSolid = STRINGIFY(
precision mediump float;
void main()
{
gl_FragColor = vec4( 1.0, 0, 0, 1 );
}
);
Program:
#import <Foundation/Foundation.h>
#include "SDL.h"
#include <time.h>
#include "SDL_opengles.h"
#include "SDL_opengles2.h"
#define FALSE 0
#define TRUE 1
#ifndef BOOL
#define BOOL int
#endif
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 480
#include "Solid.vert"
#include "Solid.frag"
GLuint g_SolidProgram = 0;
BOOL g_Running = TRUE;
SDL_Window *g_SDLWindow = NULL;
SDL_Surface *g_SDLSurface = NULL;
SDL_Renderer *g_SDLRenderer = NULL;
SDL_Texture *g_SDLTexture = NULL;
int g_ScreenHeight = SCREEN_HEIGHT;
int g_ScreenWidth = SCREEN_WIDTH;
//--------------------------------------------------------------------------------------------
// BuildShader()
//--------------------------------------------------------------------------------------------
GLuint BuildShader( char *pszSource, GLenum shaderType )
{
GLuint hShader = glCreateShader( shaderType );
glShaderSource(hShader, 1, &pszSource, 0 );
glCompileShader( hShader );
GLint compileSuccess;
if( compileSuccess == GL_FALSE )
{
GLchar message[ 256 ];
glGetShaderInfoLog( hShader, sizeof( message ), 0, &message[ 0 ] );
printf( "%s\n", message );
exit( 1 );
}
return hShader;
}
//--------------------------------------------------------------------------------------------
// BuildProgram()
//--------------------------------------------------------------------------------------------
GLuint BuildProgram( char *pszVertexShaderSource, char *pszFragmentShaderSource )
{
GLuint vShader = BuildShader( pszVertexShaderSource, GL_VERTEX_SHADER );
GLuint fShader = BuildShader( pszFragmentShaderSource, GL_FRAGMENT_SHADER );
GLuint hProgram = glCreateProgram();
glAttachShader( hProgram, vShader );
glAttachShader( hProgram, fShader );
glLinkProgram( hProgram );
GLint linkSuccess;
glGetProgramiv( hProgram, GL_LINK_STATUS, &linkSuccess );
if( linkSuccess == GL_FALSE )
{
GLchar message[ 256 ];
glGetProgramInfoLog( hProgram, sizeof( message ), 0, &message[ 0 ] );
printf( "%s\n", message );
exit( 1 );
}
return hProgram;
}
//--------------------------------------------------------------------------------------------
// ApplyOrtho()
//--------------------------------------------------------------------------------------------
void ApplyOrtho( float maxX, float maxY )
{
float a = 1.0f / maxX;
float b = 1.0f / maxY;
float ortho[ 16 ] =
{
a, 0, 0, 0,
0, b, 0, 0,
0, 0, -1, 0,
0, 0, 0, 1
};
GLint uProjection = glGetUniformLocation( g_SolidProgram, "Projection" );
glUniformMatrix4fv( uProjection, 1, 0, &ortho[ 0 ] );
}
//--------------------------------------------------------------------------------------------
// ApplyRotation()
//--------------------------------------------------------------------------------------------
void ApplyRotation( float degrees )
{
float radians = degrees * 3.14159f / 180.0f;
float s = sinf( radians );
float c = cosf( radians );
float zRotation[ 16 ] =
{
c, s, 0, 0,
-s, c, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
GLint uModelView = glGetUniformLocation( g_SolidProgram, "ModelView" );
glUniformMatrix4fv( uModelView, 1, 0, &zRotation[ 0 ] );
}
//--------------------------------------------------------------------------------------------
// InitSDL()
//--------------------------------------------------------------------------------------------
void InitSDL( void )
{
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
exit( -1 );
atexit( SDL_Quit );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
SDL_DisplayMode currentDisplay;
SDL_GetCurrentDisplayMode( 0, &currentDisplay );
g_ScreenWidth = max( currentDisplay.w, currentDisplay.h );
g_ScreenHeight = min( currentDisplay.w, currentDisplay.h );
SDL_DisplayMode displayMode;
SDL_GetDesktopDisplayMode( 0, &displayMode );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 0 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 );
g_SDLWindow = SDL_CreateWindow( "Test",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
g_ScreenWidth,
g_ScreenHeight,
/* SDL_WINDOW_FULLSCFREEN | */ SDL_WINDOW_OPENGL );
if( g_SDLWindow == NULL )
exit( -1 );
SDL_GL_CreateContext( g_SDLWindow );
glViewport( 0, 0, g_ScreenWidth, g_ScreenHeight ); // Reset The Current Viewport
glClearColor( 0.9f, 0.9f, 0.9f, 1.0f );
g_SolidProgram = BuildProgram( vsSolid, fsSolid );
glUseProgram( g_SolidProgram );
ApplyOrtho( 2, 3 );
ApplyRotation( 0 );
}
// We have to create the vertices of our triangle.
float vertices[] =
{
10.0f, 200.0f, 0.0f,
10.0f, 100.0f, 0.0f,
100.0f, 100.0f, 0.0f,
100.0f, 200.0f, 0.0f,
};
short indices[] =
{
0, 1, 2,
0, 2, 3
}; // The order of vertex rendering.
//--------------------------------------------------------------------------------------------
// Draw()
//--------------------------------------------------------------------------------------------
void Draw( int x, int y )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
GLuint hPosition = glGetAttribLocation( g_SolidProgram, "vPosition" );
glEnableVertexAttribArray( hPosition );
// Prepare the triangle coordinate data
glVertexAttribPointer( hPosition, 3, GL_FLOAT, FALSE, 0, vertices );
// Draw the triangle
glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
// Disable vertex array
glDisableVertexAttribArray( hPosition );
}
//--------------------------------------------------------------------------------------------
// main()
//--------------------------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
InitSDL();
SDL_Event event;
while( g_Running )
{
while( SDL_PollEvent( &event ) )
{
switch( event.type )
{
case SDL_QUIT:
g_Running = false;
break;
}
}
Draw( 100, 100 );
SDL_GL_SwapWindow( g_SDLWindow );
}
SDL_Quit();
return EXIT_SUCCESS;
}
The problem is the Projection * ModelView multiplier in the vertex shader. Remove that and it works.. I obviously don't understand the book content that this is derived from.
UPDATE: The vertices I was using were huge. The program below works. I hope it helps anybody else who's stuck:
#import <Foundation/Foundation.h>
#include "SDL.h"
#include <time.h>
#include "SDL_opengles.h"
#include "SDL_opengles2.h"
#define FALSE 0
#define TRUE 1
#ifndef BOOL
#define BOOL int
#endif
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 480
#include "Solid.vert"
#include "Solid.frag"
void Draw( int x, int y );
GLuint g_SolidProgram = 0;
BOOL g_Running = TRUE;
SDL_Window *g_SDLWindow = NULL;
SDL_Surface *g_SDLSurface = NULL;
SDL_Renderer *g_SDLRenderer = NULL;
SDL_Texture *g_SDLTexture = NULL;
int g_ScreenHeight = SCREEN_HEIGHT;
int g_ScreenWidth = SCREEN_WIDTH;
//--------------------------------------------------------------------------------------------
// BuildShader()
//--------------------------------------------------------------------------------------------
GLuint BuildShader( char *pszSource, GLenum shaderType )
{
GLuint hShader = glCreateShader( shaderType );
glShaderSource(hShader, 1, &pszSource, 0 );
glCompileShader( hShader );
GLint compileSuccess;
if( compileSuccess == GL_FALSE )
{
GLchar message[ 256 ];
glGetShaderInfoLog( hShader, sizeof( message ), 0, &message[ 0 ] );
printf( "%s\n", message );
exit( 1 );
}
return hShader;
}
//--------------------------------------------------------------------------------------------
// BuildProgram()
//--------------------------------------------------------------------------------------------
GLuint BuildProgram( char *pszVertexShaderSource, char *pszFragmentShaderSource )
{
GLuint vShader = BuildShader( pszVertexShaderSource, GL_VERTEX_SHADER );
GLuint fShader = BuildShader( pszFragmentShaderSource, GL_FRAGMENT_SHADER );
GLuint hProgram = glCreateProgram();
glAttachShader( hProgram, vShader );
glAttachShader( hProgram, fShader );
glLinkProgram( hProgram );
GLint linkSuccess;
glGetProgramiv( hProgram, GL_LINK_STATUS, &linkSuccess );
if( linkSuccess == GL_FALSE )
{
GLchar message[ 256 ];
glGetProgramInfoLog( hProgram, sizeof( message ), 0, &message[ 0 ] );
printf( "%s\n", message );
exit( 1 );
}
return hProgram;
}
//--------------------------------------------------------------------------------------------
// ApplyOrtho()
//--------------------------------------------------------------------------------------------
void ApplyOrtho( float maxX, float maxY )
{
float a = 1.0f / maxX;
float b = 1.0f / maxY;
float ortho[ 16 ] =
{
a, 0, 0, 0,
0, b, 0, 0,
0, 0, -1, 0,
0, 0, 0, 1
};
GLint uProjection = glGetUniformLocation( g_SolidProgram, "Projection" );
glUniformMatrix4fv( uProjection, 1, 0, &ortho[ 0 ] );
}
//--------------------------------------------------------------------------------------------
// ApplyRotation()
//--------------------------------------------------------------------------------------------
void ApplyRotation( float degrees )
{
float radians = degrees * 3.14159f / 180.0f;
float s = sinf( radians );
float c = cosf( radians );
float zRotation[ 16 ] =
{
c, s, 0, 0,
-s, c, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
GLint uModelView = glGetUniformLocation( g_SolidProgram, "ModelView" );
glUniformMatrix4fv( uModelView, 1, 0, &zRotation[ 0 ] );
}
//--------------------------------------------------------------------------------------------
// InitSDL()
//--------------------------------------------------------------------------------------------
void InitSDL( void )
{
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
exit( -1 );
atexit( SDL_Quit );
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_DisplayMode currentDisplay;
SDL_GetCurrentDisplayMode( 0, &currentDisplay );
g_ScreenWidth = max( currentDisplay.w, currentDisplay.h );
g_ScreenHeight = min( currentDisplay.w, currentDisplay.h );
SDL_DisplayMode displayMode;
SDL_GetDesktopDisplayMode( 0, &displayMode );
g_SDLWindow = SDL_CreateWindow( "Test",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
g_ScreenWidth,
g_ScreenHeight,
/* SDL_WINDOW_FULLSCFREEN | */ SDL_WINDOW_OPENGL );
if( g_SDLWindow == NULL )
exit( -1 );
SDL_GL_CreateContext( g_SDLWindow );
g_SolidProgram = BuildProgram( vsSolid, fsSolid );
glUseProgram( g_SolidProgram );
ApplyOrtho( 4, 3 );
ApplyRotation( 0 );
}
// We have to create the vertices of our triangle.
float vertices[] =
{
-0.25, -0.25, 0.0f,
-0.25, 0.25, 0,
0.25, 0.25, 0,
0.25, -0.25, 0,
};
short indices[] =
{
0, 1, 2,
0, 2, 3
}; // The order of vertex rendering.
//--------------------------------------------------------------------------------------------
// Draw()
//--------------------------------------------------------------------------------------------
void Draw( int x, int y )
{
glViewport( 0, 0, g_ScreenWidth, g_ScreenHeight ); // Reset The Current Viewport
glClearColor( 0.9f, 0.9f, 0.9f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
GLuint hPosition = glGetAttribLocation( g_SolidProgram, "vPosition" );
glEnableVertexAttribArray( hPosition );
// Prepare the triangle coordinate data
glVertexAttribPointer( hPosition, 3, GL_FLOAT, FALSE, 0, vertices );
// Draw the triangle
glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
// Disable vertex array
glDisableVertexAttribArray( hPosition );
}
//--------------------------------------------------------------------------------------------
// main()
//--------------------------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
InitSDL();
SDL_Event event;
while( g_Running )
{
while( SDL_PollEvent( &event ) )
{
switch( event.type )
{
case SDL_QUIT:
g_Running = false;
break;
}
}
Draw( 100, 100 );
SDL_GL_SwapWindow( g_SDLWindow );
}
SDL_Quit();
return EXIT_SUCCESS;
}

Moving Generated Images Down in Processing Sketch

I'm new to Processing and want to make the following sketch move images down, rather than up. I have tried adjusting the y to y+= speed in void move(), which does this but the images don't reload, they just do one cycle and the screen goes blank.
Your help would be appreciated :-)
Spot[] sp = new Spot[60];
PImage myImage;
/* #pjs preload="http://mathatelle.appspot.com/imgs/drawing_circle.png"; */
void setup() {
size(800, 400);
imageMode(CENTER);
myImage = loadImage("http://mathatelle.appspot.com/imgs/drawing_circle.png"); //100x100px
for (int i = 0; i < sp.length; i++) {
sp[i] = new Spot(random(width), random(height), random(0.2,1.0), random(0.1,1.0));
}
}
void draw() {
background(0);
for (int i = 0; i < sp.length; i++) {
sp[i].move();
sp[i].display();
}
}
class Spot {
float x, y, diameter, speed; // x座標, y座標, 直径, 速さ
Spot(float _x, float _y, float _diameter, float _speed) {
x = _x;
y = _y;
diameter = _diameter;
speed = _speed;
}
void move() {
speed *= 1.01;
y -= speed;
if (y < - myImage.width*diameter/2) {
x = random(width);
y = height + myImage.width*diameter/2;
speed = random(0.5,3);
}
}
void display() {
pushMatrix();
translate(x, y);
rotate(TWO_PI*diameter);
scale(diameter);
//tint(255, 255, 255, 153);
image(myImage, 0, 0);
popMatrix();
}
}
The logical is kind of inverted already,but just invert it again :)
here there are comments in the code:
Spot[] sp = new Spot[60];
PImage myImage;
/* #pjs preload="http://mathatelle.appspot.com/imgs/drawing_circle.png"; */
void setup() {
size(800, 400);
imageMode(CENTER);
myImage = loadImage("http://mathatelle.appspot.com/imgs/drawing_circle.png"); //100x100px
for (int i = 0; i < sp.length; i++) {
// a little change where spots are created...
sp[i] = new Spot(random(width), random(-myImage.height, height - 100), random(0.2, 1.0), random(0.1, 1.0));
}
}
void draw() {
background(0);
for (int i = 0; i < sp.length; i++) {
sp[i].move();
sp[i].display();
}
}
class Spot {
float x, y, diameter, speed; // x座標, y座標, 直径, 速さ
Spot(float _x, float _y, float _diameter, float _speed) {
x = _x;
y = _y;
diameter = _diameter;
speed = _speed;
}
void move() {
speed *= 1.01;
// invert movement direction
y += speed;
// also invert the test...
if (y > height + myImage.width*diameter/2) {
x = random(width);
y = height + myImage.width*diameter/2;
speed = random(0.5, 3);
}
}
void display() {
pushMatrix();
translate(x, y);
rotate(TWO_PI*diameter);
scale(diameter);
//tint(255, 255, 255, 153);
image(myImage, 0, 0);
popMatrix();
}
}
A friend helped me out, this is the solution to my problem :-)
Spot[] sp = new Spot[60];
PImage myImage;
/* #pjs preload="http://mathatelle.appspot.com/imgs/drawing_circle.png"; */
void setup() {
size(800, 400);
imageMode(CENTER);
myImage = loadImage("http://mathatelle.appspot.com/imgs/drawing_circle.png"); //100x100px
for (int i = 0; i < sp.length; i++) {
// a little change where spots are created...
sp[i] = new Spot(random(width), random(-myImage.height, height - 100), random(0.2, 1.0), random(0.1, 1.0));
}
}
void draw() {
background(0);
for (int i = 0; i < sp.length; i++) {
sp[i].move();
sp[i].display();
}
}
class Spot {
float x, y, diameter, speed; // x座標, y座標, 直径, 速さ
Spot(float _x, float _y, float _diameter, float _speed) {
x = _x;
y = _y;
diameter = _diameter;
speed = _speed;
}
void move() {
speed *= 1.01;
y += speed;
// change y = 0 - ...
if (y > height + myImage.width*diameter/2) {
x = random(width);
y = 0 - myImage.width*diameter/2;
speed = random(0.5, 3);
}
}
void display() {
pushMatrix();
translate(x, y);
rotate(TWO_PI*diameter);
scale(diameter);
//tint(255, 255, 255, 153);
image(myImage, 0, 0);
popMatrix();
}
}

Resources