# Copy data to OpenGL buffer

**URL:** <https://discourse.processing.org/t/copy-data-to-opengl-buffer/17709>\
**Category:** Coding Questions\
**Created:** [February 11, 2020, 12:51am UTC](https://discourse.processing.org/t/copy-data-to-opengl-buffer/17709 "2020-02-11T00:51:09Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alex\_Pr](https://avatars.discourse-cdn.com/v4/letter/a/7ba0ec/32.png) [@Alex\_Pr](https://discourse.processing.org/u/Alex_Pr)\
**Post date:** [February 11, 2020, 12:51am UTC](https://discourse.processing.org/t/copy-data-to-opengl-buffer/17709/1 "2020-02-11T00:51:09Z")

</div>

I’m trying to implement a parallax mapping shader following [this post](https://learnopengl.com/Advanced-Lighting/Parallax-Mapping).  
In the (C++) [code](https://learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/5.1.parallax_mapping/parallax_mapping.cpp), at the end of the renderQuad function, the the array quadVertices is copied into the GL Buffer. How can I do the same in Processing?

Links to the glsl files:  
[Vertex Shader](https://learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/5.1.parallax_mapping/5.1.parallax_mapping.vs)  
[Fragment Shader](https://learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/5.1.parallax_mapping/5.1.parallax_mapping.fs)

---

<div class="post-metadata">

**Author:** ![monkstone](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/monkstone/32/64_2.png) [@monkstone](https://discourse.processing.org/u/monkstone)\
**Post date:** [February 11, 2020, 6:47am UTC](https://discourse.processing.org/t/copy-data-to-opengl-buffer/17709/2 "2020-02-11T06:47:06Z")

</div>

Tutorial on [shaders for processing](https://processing.org/tutorials/pshader/) example of filters [using shaders](https://github.com/SableRaf/Filters4Processing), other [types of shaders](https://github.com/SableRaf/Shadertoy2Processing).

---

<div class="post-metadata">

**Author:** ![Alex\_Pr](https://avatars.discourse-cdn.com/v4/letter/a/7ba0ec/32.png) [@Alex\_Pr](https://discourse.processing.org/u/Alex_Pr)\
**Post date:** [February 11, 2020, 11:27am UTC](https://discourse.processing.org/t/copy-data-to-opengl-buffer/17709/3 "2020-02-11T11:27:10Z")

</div>

Thank you for the links! However, in these examples the arguments are uniform, while the shader I’m trying to implement requires vertex specific information. Any idea how I can pass that for each vertex?

I tried the following but it did not work. (The glsl files are the ones from the links in the 1st post)

```auto
void setup(){
  size(1000, 800, P3D);

  PImage bricks_dif = loadImage("bricks_diffuse.jpg");
  PImage bricks_normal = loadImage("bricks_normal.jpg");
  PImage bricks_disp = loadImage("bricks_disp.jpg");
  
  parallax = loadShader("fragmentShader2.glsl", "vertexShader2.glsl");
  parallax.set("diffuseMap", bricks_dif);
  parallax.set("normalMap", bricks_normal);
  parallax.set("depthMap", bricks_disp);
  parallax.set("heightScale", 0.2);
}

void draw(){
  background(140, 80, 80);
  
  shader(parallax);
  
  translate(width/2, height/2, 0);

  normal(0, 0, 1);
  rotateY(-PI/4);
  rotateX(PI/4);
  renderQuad();
}

void renderQuad(){
  PVector pos1 = new PVector(-1.0f, 1.0f, 0.0f);
  PVector pos2 = new PVector(-1.0f, -1.0f, 0.0f);
  PVector pos3 = new PVector( 1.0f, -1.0f, 0.0f);
  PVector pos4 = new PVector( 1.0f, 1.0f, 0.0f);
  // texture coordinates
  PVector uv1 = new PVector(0.0f, 1.0f);
  PVector uv2 = new PVector(0.0f, 0.0f);
  PVector uv3 = new PVector(1.0f, 0.0f);
  PVector uv4 = new PVector(1.0f, 1.0f);
  // normal vector
  PVector nm = new PVector(0.0f, 0.0f, 1.0f);
  
  // calculate tangent/bitangent vectors of both triangles
  PVector tangent1 = new PVector(0, 0, 0), bitangent1 = new PVector(0, 0, 0);
  PVector tangent2 = new PVector(0, 0, 0), bitangent2 = new PVector(0, 0, 0);
  // triangle 1
  // ----------
  PVector edge1 = PVector.sub(pos2, pos1);
  PVector edge2 = PVector.sub(pos3, pos1);
  PVector deltaUV1 = PVector.sub(uv2, uv1);
  PVector deltaUV2 = PVector.sub(uv3, uv1);
  
  float f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);
  
  tangent1.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
  tangent1.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
  tangent1.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
  tangent1.normalize();
  
  bitangent1.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
  bitangent1.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
  bitangent1.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
  bitangent1.normalize();
  
  // triangle 2
  // ----------
  edge1 = PVector.sub(pos3, pos1);
  edge2 = PVector.sub(pos4, pos1);
  deltaUV1 = PVector.sub(uv3, uv1);
  deltaUV2 = PVector.sub(uv4, uv1);
  
  f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);
  
  tangent2.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
  tangent2.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
  tangent2.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
  tangent2.normalize();
  
  
  bitangent2.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
  bitangent2.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
  bitangent2.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
  bitangent2.normalize();
  
  
  float quadVertices[] = {
      // positions // normal // texcoords // tangent // bitangent
      pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,
      pos2.x, pos2.y, pos2.z, nm.x, nm.y, nm.z, uv2.x, uv2.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,
      pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,
  
      pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z,
      pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z,
      pos4.x, pos4.y, pos4.z, nm.x, nm.y, nm.z, uv4.x, uv4.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z
  };
  
  int w = 300;
  
  beginShape();
  parallax.set("aPos", pos1);
  parallax.set("aNormal", nm);
  parallax.set("aTexCoords", uv1);
  parallax.set("aTangent", tangent1);
  parallax.set("aBitangent", bitangent1);
  vertex(-w, -w, 0, w, w);
  
  parallax.set("aPos", pos2);
  parallax.set("aNormal", nm);
  parallax.set("aTexCoords", uv2);
  parallax.set("aTangent", tangent1);
  parallax.set("aBitangent", bitangent1);
  vertex( w, -w, 0, 2*w, w);
  
  parallax.set("aPos", pos3);
  parallax.set("aNormal", nm);
  parallax.set("aTexCoords", uv3);
  parallax.set("aTangent", tangent1);
  parallax.set("aBitangent", bitangent1);
  vertex( w, w, 0, 2*w, 2*w);
  
  endShape(CLOSE);
  
  beginShape();
  parallax.set("aPos", pos1);
  parallax.set("aNormal", nm);
  parallax.set("aTexCoords", uv1);
  parallax.set("aTangent", tangent2);
  parallax.set("aBitangent", bitangent2);
  vertex(-w, -w, 0, w, w);
  
  parallax.set("aPos", pos3);
  parallax.set("aNormal", nm);
  parallax.set("aTexCoords", uv3);
  parallax.set("aTangent", tangent2);
  parallax.set("aBitangent", bitangent2);
  vertex( w, w, 0, 2*w, 2*w);
  
  parallax.set("aPos", pos4);
  parallax.set("aNormal", nm);
  parallax.set("aTexCoords", uv4);
  parallax.set("aTangent", tangent2);
  parallax.set("aBitangent", bitangent2);
  vertex(-w, w, 0, w, 2*w);
  
  endShape(CLOSE);
}

```

---

<div class="post-metadata">

**Author:** ![hamoid](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hamoid/32/58_2.png) [@hamoid](https://discourse.processing.org/u/hamoid)\
**Post date:** [February 11, 2020, 11:39am UTC](https://discourse.processing.org/t/copy-data-to-opengl-buffer/17709/4 "2020-02-11T11:39:12Z")

</div>

Maybe this gives you ideas: [https://github.com/processing/processing/wiki/Advanced-OpenGL](https://github.com/processing/processing/wiki/Advanced-OpenGL)

A uniform set from Processing can not be read as an attribute in the shader. You can set pos and tex coords using `vertex()`, normals using `normal()`, but the tangents I don’t know. I haven’t set custom attributes in Processing. You can search for “attribute” in the files in [https://github.com/processing/processing/tree/master/core/src/processing/opengl](https://github.com/processing/processing/tree/master/core/src/processing/opengl)

---

<div class="post-metadata">

**Author:** ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)\
**Post date:** [February 11, 2020, 2:41pm UTC](https://discourse.processing.org/t/copy-data-to-opengl-buffer/17709/5 "2020-02-11T14:41:47Z")

</div>

PShape has a whole load of methods for attaching custom vertex attributes that are exceedingly under documented! 😖 See from eg. [https://github.com/processing/processing/blob/master/core/src/processing/opengl/PShapeOpenGL.java#L1115](https://github.com/processing/processing/blob/master/core/src/processing/opengl/PShapeOpenGL.java#L1115) That might be the better way to do what you’re doing.

PGraphics also has similar attrib methods.

---

<div class="post-metadata">

**Author:** ![Alex\_Pr](https://avatars.discourse-cdn.com/v4/letter/a/7ba0ec/32.png) [@Alex\_Pr](https://discourse.processing.org/u/Alex_Pr)\
**Post date:** [February 12, 2020, 12:27am UTC](https://discourse.processing.org/t/copy-data-to-opengl-buffer/17709/6 "2020-02-12T00:27:44Z")

</div>

@neilcsmith Thank you for that, I think it is a great step in the right direction! This is what I’ve done so far, but it throws an error (multiple times)

```auto
PGraphicsOpenGL g_og;
PShader parallax;
PImage bricks_dif, bricks_normal, bricks_disp;

void settings(){
  size(1000, 800, P3D);
}

void setup(){
  g_og = (PGraphicsOpenGL)g;
  
  bricks_dif = loadImage("bricks_diffuse.jpg");
  bricks_normal = loadImage("bricks_normal.jpg");
  bricks_disp = loadImage("bricks_disp.jpg");
  
  parallax = loadShader("fragmentShader2.glsl", "vertexShader2.glsl");
  parallax.set("diffuseMap", bricks_dif);
  parallax.set("normalMap", bricks_normal);
  parallax.set("depthMap", bricks_disp);
  parallax.set("heightScale", 0.2);
  
  rectMode(CORNERS);
}

void draw(){
  background(140, 80, 80);
  
  shader(parallax);

  translate(width/2, height/2, 0);
 
  lights();
  spotLight(50, 50, 50, 800, 200, 800, -1, -0.25, -1, PI/3, 1);
  
  normal(0, 0, 1);
  rotateY(-PI/4);
  rotateX(PI/4);
  
  renderQuad();
}

void attrib(String name, PVector v, int n){
  if (n == 3){
    g_og.attrib(name, v.x, v.y, v.z);
  }
  if (n == 2){
    g_og.attrib(name, v.x, v.y);
  }
}

void renderQuad(){
  PVector pos1 = new PVector(-1.0f, 1.0f, 0.0f);
  PVector pos2 = new PVector(-1.0f, -1.0f, 0.0f);
  PVector pos3 = new PVector( 1.0f, -1.0f, 0.0f);
  PVector pos4 = new PVector( 1.0f, 1.0f, 0.0f);
  // texture coordinates
  PVector uv1 = new PVector(0.0f, 1.0f);
  PVector uv2 = new PVector(0.0f, 0.0f);
  PVector uv3 = new PVector(1.0f, 0.0f);
  PVector uv4 = new PVector(1.0f, 1.0f);
  // normal vector
  PVector nm = new PVector(0.0f, 0.0f, 1.0f);
  
  // calculate tangent/bitangent vectors of both triangles
  PVector tangent1 = new PVector(0, 0, 0), bitangent1 = new PVector(0, 0, 0);
  PVector tangent2 = new PVector(0, 0, 0), bitangent2 = new PVector(0, 0, 0);
  // triangle 1
  // ----------
  PVector edge1 = PVector.sub(pos2, pos1);
  PVector edge2 = PVector.sub(pos3, pos1);
  PVector deltaUV1 = PVector.sub(uv2, uv1);
  PVector deltaUV2 = PVector.sub(uv3, uv1);
  
  float f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);
  
  tangent1.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
  tangent1.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
  tangent1.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
  tangent1.normalize();
  
  bitangent1.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
  bitangent1.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
  bitangent1.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
  bitangent1.normalize();
  
  // triangle 2
  // ----------
  edge1 = PVector.sub(pos3, pos1);
  edge2 = PVector.sub(pos4, pos1);
  deltaUV1 = PVector.sub(uv3, uv1);
  deltaUV2 = PVector.sub(uv4, uv1);
  
  f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);
  
  tangent2.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
  tangent2.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
  tangent2.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
  tangent2.normalize();
  
  
  bitangent2.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
  bitangent2.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
  bitangent2.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
  bitangent2.normalize();
  
  
  float quadVertices[] = {
      // positions // normal // texcoords // tangent // bitangent
      pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,
      pos2.x, pos2.y, pos2.z, nm.x, nm.y, nm.z, uv2.x, uv2.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,
      pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,
  
      pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z,
      pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z,
      pos4.x, pos4.y, pos4.z, nm.x, nm.y, nm.z, uv4.x, uv4.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z
  };
  
  int w = 150;
  
  beginShape();
  texture(bricks_dif);
  
  attrib("aPos", pos1, 3);
  attrib("aNormal", nm, 3);
  attrib("aTexCoords", uv1, 2);
  attrib("aTangent", tangent1, 3);
  attrib("aBitangent", bitangent1, 3);
  vertex(-w, -w, 0, w, w);
  
  attrib("aPos", pos2, 3);
  attrib("aNormal", nm, 3);
  attrib("aTexCoords", uv2, 2);
  attrib("aTangent", tangent1, 3);
  attrib("aBitangent", bitangent1, 3);
  vertex( w, -w, 0, 2*w, w);
  
  attrib("aPos", pos3, 3);
  attrib("aNormal", nm, 3);
  attrib("aTexCoords", uv3, 2);
  attrib("aTangent", tangent1, 3);
  attrib("aBitangent", bitangent1, 3);
  vertex( w, w, 0, 2*w, 2*w);
  
  attrib("aPos", pos1, 3);
  attrib("aNormal", nm, 3);
  attrib("aTexCoords", uv1, 2);
  attrib("aTangent", tangent2, 3);
  attrib("aBitangent", bitangent2, 3);
  vertex(-w, -w, 0, w, w);
  
  attrib("aPos", pos3, 3);
  attrib("aNormal", nm, 3);
  attrib("aTexCoords", uv3, 2);
  attrib("aTangent", tangent2, 3);
  attrib("aBitangent", bitangent2, 3);
  vertex( w, w, 0, 2*w, 2*w);
  
  attrib("aPos", pos4, 3);
  attrib("aNormal", nm, 3);
  attrib("aTexCoords", uv4, 2);
  attrib("aTangent", tangent2, 3);
  attrib("aBitangent", bitangent2, 3);
  vertex(-w, w, 0, w, 2*w);
  
  endShape(CLOSE);
}

```

And the error:

```auto
java.lang.ArrayIndexOutOfBoundsException: 41
	at processing.opengl.PGraphicsOpenGL$TessGeometry.addPolyVertex(PGraphicsOpenGL.java:10301)
	at processing.opengl.PGraphicsOpenGL$Tessellator$TessellatorCallback.vertex(PGraphicsOpenGL.java:13189)
	at processing.opengl.PJOGL$Tessellator$GLUCallback.vertex(PJOGL.java:646)
	at jogamp.opengl.glu.tessellator.GLUtessellatorImpl.callVertexOrVertexData(GLUtessellatorImpl.java:616)
	at jogamp.opengl.glu.tessellator.Render$RenderFan.render(Render.java:334)
	at jogamp.opengl.glu.tessellator.Render.RenderMaximumFaceGroup(Render.java:170)
	at jogamp.opengl.glu.tessellator.Render.__gl_renderMesh(Render.java:116)
	at jogamp.opengl.glu.tessellator.GLUtessellatorImpl.gluTessEndPolygon(GLUtessellatorImpl.java:556)
	at com.jogamp.opengl.glu.GLU.gluTessEndPolygon(GLU.java:896)
	at processing.opengl.PJOGL$Tessellator.endPolygon(PJOGL.java:610)
	at processing.opengl.PGraphicsOpenGL$Tessellator.tessellatePolygon(PGraphicsOpenGL.java:12612)
	at processing.opengl.PGraphicsOpenGL.tessellate(PGraphicsOpenGL.java:2288)
	at processing.opengl.PGraphicsOpenGL.endShape(PGraphicsOpenGL.java:2001)
	at processing.core.PApplet.endShape(PApplet.java:11080)
	at parallax_mapping_2.renderQuad(parallax_mapping_2.java:201)
	at parallax_mapping_2.draw(parallax_mapping_2.java:72)
	at processing.core.PApplet.handleDraw(PApplet.java:2412)
	at processing.opengl.PSurfaceJOGL$DrawListener.display(PSurfaceJOGL.java:871)
	at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:692)
	at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:674)
	at jogamp.opengl.GLAutoDrawableBase$2.run(GLAutoDrawableBase.java:443)
	at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1293)
	at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1147)
	at com.jogamp.newt.opengl.GLWindow.display(GLWindow.java:759)
	at com.jogamp.opengl.util.AWTAnimatorImpl.display(AWTAnimatorImpl.java:81)
	at com.jogamp.opengl.util.AnimatorBase.display(AnimatorBase.java:452)
	at com.jogamp.opengl.util.FPSAnimator$MainTask.run(FPSAnimator.java:178)
	at java.util.TimerThread.mainLoop(Timer.java:555)
	at java.util.TimerThread.run(Timer.java:505)

```

I looked into the PGraphicsOpenGL implementation to try to determine what is causing this but it didn’t work 😛 Any ideas on that?

---

<div class="post-metadata">

**Author:** ![Behzod27](https://avatars.discourse-cdn.com/v4/letter/b/db5fbb/32.png) [@Behzod27](https://discourse.processing.org/u/Behzod27)\
**Post date:** [June 28, 2022, 6:32am UTC](https://discourse.processing.org/t/copy-data-to-opengl-buffer/17709/7 "2022-06-28T06:32:30Z")

</div>

// Exemplifies the use of the ppixels uniform in the shader, that gives  
// access to the pixels of the previous frame.

See also processing-3.5.4\modes\java\examples\Topics\Shaders\Conway.pde

i think it is useful for you
