Processingでシェーダをいじる旅

こんにちわ。きょうはProcessingでシェーダをいじる旅に出ましょう。
これは「Processing Advent Calender2015」の21ばんめの参加記事です。

あらすじ

IMG_4776.PNG
結果的に間に合わなかったので「シェーダをいじる旅に出たら迷ったまでの記録」と改題します。 ~~ほかにネタもないし放っておいてもいずれ誰か書くだろうので先手を打つぞ~~
※随時更新する予定です。ぜったいにいつか 「がんばってProcessingでGPGPUパーティクルを実装した!GPGPGPUPだ!」 って言うんだ・・・

おさらい

Processingでシェーダをいじるといえば2.x時代に機能が追加されてからすぐの、p5infoさんによるこちらの記事を参考にするのがたいへんに良い感じです。こちらの記事ではフラグメントシェーダに重きをおいた説明で、バーテックスシェーダをやってみたやつはちょっと前に書きました。あとは公式の解説を読めばなんとなく分かったふうな感じになってきます。

なってきましたか。わたしは英語が読めないのでわからなかったですが。

3.x時代

についてはここらへんにありました。ありがたいことにサンプルがついているのでこいつを雛形にします。

あとはゴッドオブザWebGLのドクサスさんのサイトに沿って旅に出ます。丁寧にググッて大胆にコピペ。
vsp.png


2015-12-20 19.20.28.png


いい感じにシェーダで書いたっぽいやつができましたね。



ソースコードを置いておきます。動かないときはグラポを疑ってください。PeasyCam入れてないひとはすぐいれるんだ。

class Ita{
  int[] index = {};
  float[] vertex = {};
  float[] normal = {};
  float[] texcoord = {};
  Ita(int X, int Y){
    if(X<2) X=2;
    if(Y<2) Y=2;
    X -= 1;
    Y -= 1;
    for(int y=0; y<Y; y++){
      for(int x=0; x<X; x++){
        int r = (X+1)*y+x;
        index = append(index, r);
        index = append(index, r+1);
        index = append(index, r+X+1);

        index = append(index, r+X+2);
        index = append(index, r+X+1);
        index = append(index, r+1);        
      }
    }
    X+=1;
    Y+=1;
    for(int n=0; n<X*Y; n++){
      normal = append(normal, .0);
      normal = append(normal, .0);
      normal = append(normal, 1.0);
    }

    float divX = 2/(float)(X-1);
    float divY = 2/(float)(Y-1);

    for(float y=1; y>=-1; y-=divY){
      for(float x=-1; x<=1; x+=divX){
          vertex = append(vertex, x);
          vertex = append(vertex, y);
          vertex = append(vertex, 0);
        }
      }

    divX = 1/(float)(X-1);
    divY = 1/(float)(Y-1);
    for(float y=0; y<=1; y+=divY){
      for(float x=0; x<=1; x+=divX){
          texcoord = append(texcoord, x);
          texcoord = append(texcoord, y);
        }
      }

  }
}
class Sphere{
  float[] pos = {};
  int[] idx = {};
  float[] col = {};
  float[] nor = {};
  int i, j;
  float[] tc = {};

  Sphere(int row, int column, float rad){
    for(i=0; i<=row; i++){
      float r = PI/row*i;
      float ry = cos(r);
      float rr = sin(r);
      for(j=0; j<=column; j++){
        float tr = PI*2 / column * j;
        float tx = rr * rad * cos(tr);
        float ty = ry * rad;
        float tz = rr * rad * sin(tr);
        float rx = rr * cos(tr);
        float rz = rr * sin(tr);

        tc = hsva(360 / row * i, 1, 1, 1);

        pos = append(pos, tx);
        pos = append(pos, ty);
        pos = append(pos, tz);

        nor = append(nor, rx);
        nor = append(nor, ry);
        nor = append(nor, rz);

        col = append(col, tc[0]);
        col = append(col, tc[1]);
        col = append(col, tc[2]);
        col = append(col, tc[3]);
      }
    }
    int r=0;
    for(i=0; i<row; i++){
      for(j=0; j<column; j++){
        r = (column + 1) * i + j;
        idx = append(idx, r + column + 2);
        idx = append(idx, r + 1);
        idx = append(idx, r);

        idx = append(idx, r + column + 1);
        idx = append(idx, r + column + 2);
        idx = append(idx, r);
      }
    }
  }

  float[] hsva(float h, float s, float v, float a){
    if( !(s>1 || v>1 || a>1) ){
      float th = h % 360;
      int i = floor(th/60);
      float f = th/60 - i;
      float m = v*(1-s);
      float n = v*(1-s*f);
      float k = v*(1-s*(1-f));
      float[] c = {};
      if(!(s>0) && !(s<0)){
        c = append(c, v);
        c = append(c, v);
        c = append(c, v);
        c = append(c, a);
      }else{
        float[] r = {v, n, m, m, k, v};
        float[] g = {k, v, v, n, m, m};
        float[] b = {m, m, k, v, v, n};
        c = append(c, r[i]);
        c = append(c, g[i]);
        c = append(c, b[i]);
        c = append(c, a);
      }
      return c;
    }else{
      return null;
    }
  }
}
String[] vig_vert = {
  "#version 150",
  "in vec4 position;",
  "void main(){",
    "gl_Position = position;",
  "}"
};

String[] vig_frag = {
  "#version 150",
  "uniform vec2 res;",
  "out vec4 fragColor;",
  "const float rad = .9;",
  "const float softness = .7;",
  "void main(){", 
    "vec2 pos = gl_FragCoord.st/res - vec2(.5);",
    "float len = length(pos);",
    "fragColor = vec4(vec3(smoothstep(rad, rad-softness,len)), .9);",
  "}"

};

String sphere_vert[] = {
    "#version 150",  
    "uniform mat4 transform;",
    "in vec4 position;", 
    "in vec4 color;",
    "in vec3 normal;",
    "out vec4 vertColor;",
    "out vec3 vertNormal;",
    "void main() {",
      "vertNormal = normal;",
      "vertColor = color;",
      "gl_Position = transform * position;", 
    "}"
};

String sphere_frag[] = {
    "#version 150",
    "uniform mat4 invMat;",
    "uniform vec3 lightVec;",
    "uniform vec4 ambientLight;",
    "uniform vec3 eye;",

    "in vec4 vertColor;",
    "in vec3 vertNormal;",
    "out vec4 fragColor;",    
    "void main() {",
      "vec3 normalizeLight = normalize(vec4(lightVec, .0) * invMat).xyz;",
      "vec3 invEye = normalize(vec4(eye, .0) * invMat).xyz;",
      "float dif = clamp(dot(vertNormal, normalizeLight), .0, 1.0);",
      "vec3 halfV = normalize(normalizeLight + invEye);",
      "float specular = pow(clamp(dot(vertNormal, halfV), .0, 1.0), 50.0);",
      "fragColor = vec4(vertColor.rgb*dif, vertColor.a)+ambientLight + vec4(vec3(specular), .0);",
    "}"
 };

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2GL3;

import peasy.*;
PeasyCam cam;

PShader shader, vignette;
PGraphics pg;
PImage vignetteImage;

Sphere s;
Ita ita;
PMatrix3D model;

float[] vertices;
FloatBuffer posBuffer;
int vertexBuffer; 

int[] indices;
IntBuffer idxBuffer;
int indexBuffer;

float[] colors;
FloatBuffer clrBuffer;
int colorBuffer;

float[] normals;
FloatBuffer nrmBuffer;
int normalBuffer;

float[] itaPositions;
FloatBuffer itaPosData;
int itaPositionBufferID;

int[] itaIndices;
IntBuffer itaIdxData;
int itaIndexBufferID;

FloatBuffer modelMatrix;

PJOGL pgl;
GL2GL3 gl;

// if you need more advanced functionality
//available in higher profiles ,
//you can explicitly request profiles 3 and 4 by using below
/*
void setting(){
  size(800, 600, P3D);
  PJOGL.profile = 4;
}
*/

void setup() {
  size(512, 512, P3D);
  cam = new PeasyCam(this, 200);
  cam.setMinimumDistance(.1);
  cam.setMaximumDistance(100); 

  vignette = new PShader(this, vig_vert, vig_frag);
  ita = new Ita(2,2);
  pg = createGraphics(width, height, P3D);
  itaPositions = ita.vertex;
  itaIndices = ita.index;
  itaPosData = allocateDirectFloatBuffer(itaPositions.length);
  itaIdxData = allocateDirectIntBuffer(itaIndices.length);
  itaPosData.rewind();
  itaPosData.put(itaPositions);
  itaPosData.rewind();
  itaIdxData.rewind();
  itaIdxData.put(itaIndices);
  itaIdxData.rewind();  
  pg.beginDraw();
  pgl = (PJOGL)beginPGL();
  gl = pgl.gl.getGL2GL3();

  IntBuffer intBuf = IntBuffer.allocate(2);
  gl.glGenBuffers(2, intBuf);
  itaPositionBufferID = intBuf.get(0);
  itaIndexBufferID = intBuf.get(1);  
  vignette.bind();
  gl.glBindBuffer(GL.GL_ARRAY_BUFFER, itaPositionBufferID);
  gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * itaPositions.length, itaPosData, GL.GL_STATIC_DRAW);
  int itaLoc = gl.glGetAttribLocation(vignette.glProgram, "position");
  gl.glEnableVertexAttribArray(itaLoc);
  gl.glVertexAttribPointer(itaLoc, 3, GL.GL_FLOAT, false, 0, 0);

  gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, itaIndexBufferID);
  gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, Integer.BYTES * itaIndices.length, itaIdxData, GL.GL_STATIC_DRAW);

  int resLoc = gl.glGetUniformLocation(vignette.glProgram, "res");
  gl.glUniform2f(resLoc, width, height);

  gl.glDrawElements(PGL.TRIANGLES, itaIndices.length, GL.GL_UNSIGNED_INT, 0);
  vignette.unbind();
  pg.endDraw();
  endPGL();
  vignetteImage = pg;

  shader = new PShader(this, sphere_vert, sphere_frag);
  s = new Sphere(16, 16, 30);

  posBuffer = allocateDirectFloatBuffer(s.pos.length);
  idxBuffer = allocateDirectIntBuffer(s.idx.length);
  clrBuffer = allocateDirectFloatBuffer(s.col.length);
  nrmBuffer = allocateDirectFloatBuffer(s.nor.length);

  modelMatrix = allocateDirectFloatBuffer(16);

  pgl = (PJOGL) beginPGL();  
  gl = pgl.gl.getGL2GL3();

  IntBuffer intBuffer = IntBuffer.allocate(4);
  gl.glGenBuffers(4, intBuffer);
  vertexBuffer = intBuffer.get(0);
  indexBuffer = intBuffer.get(1);
  colorBuffer = intBuffer.get(2);
  normalBuffer = intBuffer.get(3);

  gl.glEnable(GL.GL_DEPTH_TEST);
  gl.glDepthFunc(GL.GL_LEQUAL);


  endPGL();
  PMatrix3D viewMat = (PMatrix3D)g.getMatrix();
  print(viewMat.m00 + " " + viewMat.m01 + " ");
  println(viewMat.m02 + " " + viewMat.m03 + " ");
  print(viewMat.m10 + " " + viewMat.m11 + " ");
  println(viewMat.m12 + " " + viewMat.m13 + " ");
  print(viewMat.m20 + " " + viewMat.m21 + " ");
  println(viewMat.m22 + " " + viewMat.m23 + " ");
  print(viewMat.m30 + " " + viewMat.m31 + " ");
  println(viewMat.m32 + " " + viewMat.m33 + " ");

}

void draw() {
  pushMatrix();
  translate(0, 0, 0);
  cam.beginHUD();
  image(pg,0,0);
  cam.endHUD();
  popMatrix();
  rotateY(frameCount*.008);
  rotateZ(frameCount*-.002);
  pushMatrix();
  resetMatrix();
  rotateY(frameCount*.008);
  rotateZ(frameCount*-.002);

  model = (PMatrix3D)g.getMatrix();
  popMatrix();

  /*
  pushMatrix();
  resetMatrix();
  printMatrix();
  println("カメラ位置;");
  println(cam.getPosition() );
  println("lookat");
  println(cam.getLookAt());
  popMatrix();
  */

  updateGeometry();

  pgl = (PJOGL) beginPGL();  
  gl = pgl.gl.getGL2GL3();

  shader.bind();
  gl.glClearColor(.4, .2, .6, 1.0);
  gl.glClearDepth(1.0);

//  gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
  gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
  int attLoc = gl.glGetAttribLocation(shader.glProgram, "position");
  int colLoc = gl.glGetAttribLocation(shader.glProgram, "color");
  int nrmLoc = gl.glGetAttribLocation(shader.glProgram, "normal");

  int uniLoc_DirectionLight = gl.glGetUniformLocation(shader.glProgram, "lightVec");
  int uniLoc_invMat = gl.glGetUniformLocation(shader.glProgram, "invMat");
  int uniLoc_ambientLight = gl.glGetUniformLocation(shader.glProgram, "ambientLight");

  PVector eyePos = new PVector(cam.getPosition()[0], cam.getPosition()[1], cam.getPosition()[2]);
  PVector eyeDir = eyePos.sub(cam.getLookAt()[0], cam.getLookAt()[1], cam.getLookAt()[2]);
  int uniLoc_eyeVec = gl.glGetUniformLocation(shader.glProgram, "eye");
  println(eyeDir);


  gl.glUniform3f(uniLoc_DirectionLight, .5, -.5, .5);
  gl.glUniform4f(uniLoc_ambientLight, .15, .15, .15, .2);
  gl.glUniform3f(uniLoc_eyeVec, eyeDir.x, eyeDir.y, eyeDir.z); 
  model.invert();              
  modelMatrix.rewind();
  modelMatrix.put(model.m00); 
  modelMatrix.put(model.m01);
  modelMatrix.put(model.m02);
  modelMatrix.put(model.m03);
  modelMatrix.put(model.m10);
  modelMatrix.put(model.m11);
  modelMatrix.put(model.m12);
  modelMatrix.put(model.m13);
  modelMatrix.put(model.m20);
  modelMatrix.put(model.m21);
  modelMatrix.put(model.m22);
  modelMatrix.put(model.m23);
  modelMatrix.put(model.m30);
  modelMatrix.put(model.m31);
  modelMatrix.put(model.m32);
  modelMatrix.put(model.m33);
  modelMatrix.rewind();
  gl.glUniformMatrix4fv(uniLoc_invMat, 1, false, modelMatrix);

  gl.glEnableVertexAttribArray(attLoc);
  gl.glEnableVertexAttribArray(colLoc);
  gl.glEnableVertexAttribArray(nrmLoc);

  gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBuffer);
  gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * vertices.length, posBuffer, GL.GL_STATIC_DRAW); 
  gl.glVertexAttribPointer(attLoc, 3, GL.GL_FLOAT, false, 0, 0);

  gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
  gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, Integer.BYTES * indices.length, idxBuffer, GL.GL_DYNAMIC_DRAW);

  gl.glBindBuffer(GL.GL_ARRAY_BUFFER, colorBuffer);
  gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * colors.length, clrBuffer, GL.GL_DYNAMIC_DRAW);
  gl.glVertexAttribPointer(colLoc, 4, GL.GL_FLOAT, false, 0, 0);

  gl.glBindBuffer(GL.GL_ARRAY_BUFFER, normalBuffer);
  gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * normals.length, nrmBuffer, GL.GL_STATIC_DRAW);
  gl.glVertexAttribPointer(nrmLoc, 3, GL.GL_FLOAT, false, 0, 0);

 // gl.glDrawArrays(PGL.TRIANGLES, 0, vertices.length/3);
  gl.glDrawElements(PGL.TRIANGLES, indices.length, GL.GL_UNSIGNED_INT, 0);

  gl.glDisableVertexAttribArray(attLoc);
  gl.glDisableVertexAttribArray(colLoc);
  shader.unbind();

  endPGL();

}

void updateGeometry() {

  vertices = s.pos;
  indices = s.idx;
  colors = s.col;
  normals = s.nor;

  posBuffer.rewind();
  posBuffer.put(vertices); 
  posBuffer.rewind();

  idxBuffer.rewind();
  idxBuffer.put(indices); 
  idxBuffer.rewind();

  clrBuffer.rewind();
  clrBuffer.put(colors); 
  clrBuffer.rewind();

  nrmBuffer.rewind();
  nrmBuffer.put(normals);
  nrmBuffer.rewind();
}  

FloatBuffer allocateDirectFloatBuffer(int n) {
  return ByteBuffer.allocateDirect(n * Float.BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
}

IntBuffer allocateDirectIntBuffer(int n) {
  return ByteBuffer.allocateDirect(n * Integer.BYTES).order(ByteOrder.nativeOrder()).asIntBuffer();
}

にばんめのやつ

class Ita{
  int[] index = {};
  float[] vertex = {};
  float[] normal = {};
  float[] texcoord = {};
  Ita(int X, int Y, float scale){
    if(X<2) X=2;
    if(Y<2) Y=2;
    X -= 1;
    Y -= 1;
    for(int y=0; y<Y; y++){
      for(int x=0; x<X; x++){
        int r = (X+1)*y+x;
        //triangle mesh 1
        index = append(index, r);
        index = append(index, r+1);
        index = append(index, r+X+1);
        //tirangle mesh 2
        index = append(index, r+X+2);
        index = append(index, r+X+1);
        index = append(index, r+1);        
      }
    }
    X+=1;
    Y+=1;
    for(int n=0; n<X*Y; n++){
      //normal ordered x,y,z
      normal = append(normal, .0);
      normal = append(normal, .0);
      normal = append(normal, 1.0);
    }

    float divX = 2/(float)(X-1);
    float divY = 2/(float)(Y-1);


    for(float y=1; y>=-1; y-=divY){
      for(float x=-1; x<=1; x+=divX){
          vertex = append(vertex, x*scale);
          vertex = append(vertex, y*scale);
          vertex = append(vertex, 0);
        }
      }

    divX = 1/(float)(X-1);
    divY = 1/(float)(Y-1);
    for(float y=0; y<=1; y+=divY){
      for(float x=0; x<=1; x+=divX){
          texcoord = append(texcoord, x);
          texcoord = append(texcoord, y);
        }
      }

  }
}
class Sphere{
  float[] pos = {};
  int[] idx = {};
  float[] col = {};
  float[] nor = {};

  int i, j;
  float[] tc = {};


  Sphere(int row, int column, float rad){
    for(i=0; i<row; i++){
      float r = PI/row*i;
      float ry = cos(r);
      float rr = sin(r);
      for(j=0; j<column; j++){
        float tr = PI*2 / column * j;
        float tx = rr * rad * cos(tr);
        float ty = ry * rad;
        float tz = rr * rad * sin(tr);
        float rx = rr * cos(tr);
        float rz = rr * sin(tr);

        tc = hsva(360 / row * i, 1, 1, 1);

        pos = append(pos, tx);
        pos = append(pos, ty);
        pos = append(pos, tz);

        nor = append(nor, rx);
        nor = append(nor, ry);
        nor = append(nor, rz);

        col = append(col, tc[0]);
        col = append(col, tc[1]);
        col = append(col, tc[2]);
        col = append(col, tc[3]);
      }
    }

    //インデックス
    int r=0;
    for(i=0; i<row; i++){
      for(j=0; j<column; j++){
        r = (column + 1) * i + j;
        idx = append(idx, r + column + 2);
        idx = append(idx, r + 1);
        idx = append(idx, r);

        idx = append(idx, r + column + 1);
        idx = append(idx, r + column + 2);
        idx = append(idx, r);
      }
    }
  }

  float[] hsva(float h, float s, float v, float a){
    if( !(s>1 || v>1 || a>1) ){
      float th = h % 360;
      int i = floor(th/60);
      float f = th/60 - i;
      float m = v*(1-s);
      float n = v*(1-s*f);
      float k = v*(1-s*(1-f));
      float[] c = {};
      if(!(s>0) && !(s<0)){
        c = append(c, v);
        c = append(c, v);
        c = append(c, v);
        c = append(c, a);
      }else{
        float[] r = {v, n, m, m, k, v};
        float[] g = {k, v, v, n, m, m};
        float[] b = {m, m, k, v, v, n};
        c = append(c, r[i]);
        c = append(c, g[i]);
        c = append(c, b[i]);
        c = append(c, a);
      }
      return c;
    }else{
      return null;    //要検証
    }
  }
}

String[] map_vert = {
  "#version 150",
  "in vec3 map_position;",
  "in vec3 map_itapos;",
  "in float map_index;",
  "out vec3 vColor;",
  "const float frag = 1.0/"+(float)Rsize+";",
  "const float texShift = .5*frag;",
  "void main(){",
    "vColor = (normalize(map_position)+1.0)*.5;",    
    "gl_Position = vec4(map_itapos.x+texShift, map_itapos.y+texShift, .0, 1.0);",
//    "gl_Position = vec4(pu+texShift, pv+texShift, .0, 1.0);",
    "gl_PointSize = 1.0;",
  "}"
};

String[] map_frag = {
  "#version 150",
  "in vec3 vColor;",
  "out vec4 fragColor;",
  "void main(){",
    "fragColor = vec4(vColor, 1.0);",
  "}"
};

String[] vtf_vert = {
  "#version 150",
  "in vec3 vtf_itapos;",
  "uniform mat4 transform;",
  "uniform sampler2D tex0;",
  "const float frag = 1.0/"+(float)Rsize+";",
  "const float texShift = .5*frag;",
  "void main(){",
    "vec3 texPos = texture(tex0, vec2(vtf_itapos.x, vtf_itapos.y)).rgb*2-1.0;",
    "gl_Position = transform*vec4(texPos*50.0, 1.0);",
    "gl_PointSize = 900.0/gl_Position.w;", 
  "}"
};

String[] vtf_frag = {
  "#version 150",
  "uniform sampler2D tex0;",
  "out vec4 fragColor;",
  "uniform vec2 res;",
  "void main(){",
    "vec2 pos = gl_PointCoord*2 - 1;",
    "float n = 1.0-dot(pos, pos);",
    "if(n<.0)discard;",
    "float lnh = .5/length(pos);",
//    "fragColor = texture(tex0, gl_PointCoord);",

    "fragColor = vec4(vec3(lnh), lnh*lnh);",
"}"

};
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2GL3;

import peasy.*;

PJOGL pgl;
GL2GL3 gl;

Ita ita;
Sphere s;
PGraphics pg;
PShader offscreentest, vtftest;
PeasyCam cam;

float[] map_positions;
FloatBuffer map_posData;
int map_positionBufferID;

int[] map_indices = {};
IntBuffer map_idxData;
int map_indexBufferID;

float[] map_itapos;
FloatBuffer map_itaData;
int map_itaBufferID;

float[] vtf_positins4texCoords;
FloatBuffer vtf_pos4texData;
int vtf_position4texCoordBufferID;
int texLoc;
int[] texpix;

static final int Rsize=32;

void setup(){
  size(400, 400, P3D);
  cam = new PeasyCam(this, 100);
  cam.setMinimumDistance(.1);
  cam.setMaximumDistance(100.0);

  pushMatrix();
  pg=createGraphics(Rsize-1 ,Rsize-1, P3D);
  offscreentest = new PShader(this, map_vert, map_frag);
  vtftest = new PShader(this, vtf_vert, vtf_frag);
  ita = new Ita(Rsize, Rsize, 1);
  s = new Sphere(Rsize, Rsize, 5.0);

  map_positions = s.pos;

  for(int i=0; i<map_positions.length/3; i++){
    map_indices = append(map_indices, i);
  }

  map_itapos = ita.vertex;
  map_posData = allocateDirectFloatBuffer(map_positions.length);
  map_idxData = allocateDirectIntBuffer(map_indices.length);
  map_itaData = allocateDirectFloatBuffer(map_itapos.length);
  map_posData.rewind();
  map_posData.put(map_positions);
  map_posData.rewind();
  map_idxData.rewind();
  map_idxData.put(map_indices);
  map_idxData.rewind();
  map_itaData.rewind();
  map_itaData.put(map_itapos);
  map_itaData.rewind();

  offscreentest.bind();
  pgl = (PJOGL)beginPGL();
  gl = pgl.gl.getGL2GL3();

  IntBuffer texmap = IntBuffer.allocate(3);
  gl.glGenBuffers(3, texmap);
  map_positionBufferID = texmap.get(0);
  map_indexBufferID = texmap.get(1);
  map_itaBufferID = texmap.get(2);

  gl.glBindBuffer(GL.GL_ARRAY_BUFFER, map_positionBufferID);
  gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * map_positions.length, map_posData, GL.GL_STATIC_DRAW);
  int map_posLoc = gl.glGetAttribLocation(offscreentest.glProgram, "map_position");
  gl.glEnableVertexAttribArray(map_posLoc);
  gl.glVertexAttribPointer(map_posLoc, 3, GL.GL_FLOAT, false, 0, 0);

  gl.glBindBuffer(GL.GL_ARRAY_BUFFER, map_itaBufferID);
  gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * map_itapos.length, map_itaData, GL.GL_STATIC_DRAW);
  int map_itaLoc = gl.glGetAttribLocation(offscreentest.glProgram, "map_itapos");
  gl.glEnableVertexAttribArray(map_itaLoc);
  gl.glVertexAttribPointer(map_itaLoc, 3, GL.GL_FLOAT, false, 0, 0);

  pg.beginDraw();
  gl.glPointSize(1.0);
  gl.glDrawArrays(PGL.POINTS, 0, map_indices.length);
  pg.endDraw();
  gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
  gl.glDisableVertexAttribArray(map_posLoc);
  gl.glDisableVertexAttribArray(map_itaLoc);
  offscreentest.unbind();

  popMatrix();  
  endPGL();

  vtf_positins4texCoords = ita.vertex;
  vtf_pos4texData = allocateDirectFloatBuffer(vtf_positins4texCoords.length);
  vtf_pos4texData.rewind();
  vtf_pos4texData.put(vtf_positins4texCoords);
  vtf_pos4texData.rewind();

  pgl=(PJOGL)beginPGL();
  gl=pgl.gl.getGL2GL3();
  IntBuffer vtfBuf = IntBuffer.allocate(1);
  gl.glGenBuffers(1, vtfBuf);
  vtf_position4texCoordBufferID = vtfBuf.get(0);

  texLoc = gl.glGetUniformLocation(vtftest.glProgram, "tex0");
    gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
    gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
    gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
    gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
    gl.glActiveTexture(GL.GL_TEXTURE0);
  IntBuffer texBuf = IntBuffer.allocate(1);
  gl.glGenTextures(1, texBuf);
  gl.glBindTexture(GL.GL_TEXTURE_2D, texBuf.get(0));

//  argb2abgr(pg);
  pg.loadPixels();
  texpix = pg.pixels;
  pg.updatePixels();
  gl.glGenerateMipmap(GL.GL_TEXTURE_2D);
  gl.glBindTexture(GL.GL_TEXTURE_2D, 0);

  gl.glEnable(GL.GL_TEXTURE_2D);
  gl.glEnable(GL.GL_DEPTH_TEST);
  gl.glEnable(0x8642);  //謎過ぎてウケるけど助かった
  gl.glDepthFunc(GL.GL_LEQUAL);
  endPGL();
}

void draw(){
  blendMode(BLEND);
  rotateX(frameCount*.003);
  rotateY(frameCount*.008);
  pgl = (PJOGL)beginPGL();
  gl = pgl.gl.getGL2GL3();
  vtftest.bind();
  gl.glClearColor(.3, .6, .8, 1.0);
  gl.glClearDepth(1.0);
  gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

  gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vtf_position4texCoordBufferID);
  gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * vtf_positins4texCoords.length, vtf_pos4texData, GL.GL_STATIC_DRAW);
  int attLoc = gl.glGetAttribLocation(vtftest.glProgram, "vtf_itapos");
  gl.glEnableVertexAttribArray(attLoc);
  gl.glVertexAttribPointer(attLoc, 3, GL.GL_FLOAT, false, 0, 0);

  gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, pg.width, pg.height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, IntBuffer.wrap(texpix)); 
  gl.glUniform1i(texLoc, 0);

  int resLoc = gl.glGetUniformLocation(vtftest.glProgram, "res");
  gl.glUniform2f(resLoc, 10, 10);

  gl.glDrawArrays(PGL.POINTS, 0, vtf_positins4texCoords.length/3);
  vtftest.unbind();
  endPGL();
  pushMatrix();
  cam.beginHUD();
  image(pg, 10, 10, 50, 50);
  cam.endHUD();
  popMatrix();
}

FloatBuffer allocateDirectFloatBuffer(int n) {
  return ByteBuffer.allocateDirect(n * Float.BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
}

IntBuffer allocateDirectIntBuffer(int n) {
  return ByteBuffer.allocateDirect(n * Integer.BYTES).order(ByteOrder.nativeOrder()).asIntBuffer();
}

PImage argb2abgr(PImage _img){
    _img.loadPixels();
  for(int y=0; y<_img.height; y++){
    for(int x=0; x<_img.width; x++){
      int pos = y*_img.width+x;
      color clr = _img.pixels[pos];
      int r= clr >> 24&0xff;
      int g= clr >> 16&0xff;
      int b= clr >> 8&0xff;
      int a= clr    &0xff;
      _img.pixels[pos]=color(a,b,g,r);
    }
  }
  _img.updatePixels();
  return _img;
}

Processingを使えばかんたんにシェーダの勉強もできました。3DCGプログラミングの勉強は無限に時間をつぶせますね。無職の身にはありがたいものです。
読んでくださりありがとうございました。

小ネタ

外部からシェーダソースを読み込む時、シェーダの拡張子はべつになんでもいいのでモチベあがる名前をつけてあげましょう

niconiconii

Written on December 21, 2015