Trying to port a glass effect shader on Processing 3.0

edited April 2016 in GLSL / Shaders

Hi, friends!

I am new on forum, and really a beginner on shaders. I am trying to port a fresnel+cubemap shader for a glass material. But as result my shape ever disappear, instead... :-(

Some friend have a hint about what I am doing wrong? I am rendering it on Android mode, on emulator.

That is my minimal sketch:


import java.nio.IntBuffer;
PShader shader;
PShape sphere;
PShape box;

void setup() {
  fullScreen(P3D);
  noStroke();
  shader = loadShader("glass.frag.glsl", "glass.vert.glsl");
  openCubeMap("posx.png", "negx.png", "posy.png", "negy.png", "posz.png", "negz.png");
  shader.set("cubemap", 1);

  sphere = createShape(SPHERE, 120);
  sphere.setFill(color(-1, 50));

  box = createShape(BOX, 100);
  box.setFill(color(255, 50, 50));
} 

void draw() {
  background(0);      
  // Some lights...
  directionalLight(102, 102, 102, 0, 0, -1);
  lightSpecular(204, 204, 204);
  directionalLight(102, 102, 102, 0, 1, -1);
  specular(100, 150, 150);

  pushMatrix();
  translate(width / 2, height / 2);
  rotateY(90);
  rotateX(45);
  shape(box);
  popMatrix();

  translate(mouseX, mouseY);  
  shader(shader);
  shape(sphere);
  resetShader();
}  

I use this method to load the textures (from data dir) on cubemap:

void openCubeMap(String posX, String negX, String posY, String negY, String posZ, String negZ) {
  PGL pgl = beginPGL();
  IntBuffer envMapTextureID = IntBuffer.allocate(1);
  pgl.genTextures(1, envMapTextureID);
  pgl.activeTexture(PGL.TEXTURE1);
  pgl.enable(PGL.TEXTURE_CUBE_MAP);  
  pgl.bindTexture(PGL.TEXTURE_CUBE_MAP, envMapTextureID.get(0));
  pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_WRAP_S, PGL.CLAMP_TO_EDGE);
  pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_WRAP_T, PGL.CLAMP_TO_EDGE);
  pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_WRAP_R, PGL.CLAMP_TO_EDGE);
  pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_MIN_FILTER, PGL.LINEAR);
  pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_MAG_FILTER, PGL.LINEAR);

  //Load in textures
  String[] textureNames = { posX, negX, posY, negY, posZ, negZ };
  PImage[] textures = new PImage[textureNames.length];
  for (int i=0; i < textures.length; i++) {    
    textures[i] = loadImage(textureNames[i]);
    if (textures[i] == null) {
      throw new IllegalArgumentException("Fail to load " + textureNames[i]);
    }
  }

  // put the textures in the cubeMap
  int envMapSize = 0;
  for (int i=0; i < textures.length; i++) {
    int w = textures[i].width;
    int h = textures[i].height;
    envMapSize = Math.max(Math.max(w, h), envMapSize);
    textures[i].loadPixels();
    int[] pix = textures[i].pixels;
    pgl.texImage2D(PGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, PGL.RGBA, w, h, 0, PGL.RGBA, PGL.UNSIGNED_BYTE, java.nio.IntBuffer.wrap(pix));
  }

  endPGL();
}  

This is my vertex shader:


#version 120

// Indices of refraction
const float Air = 1.0;
const float Glass = 1.51714;

// Air to glass ratio of the indices of refraction (Eta)
const float Eta = Air / Glass;
 
// see http://en.wikipedia.org/wiki/Refractive_index Reflectivity
const float R0 = ((Air - Glass) * (Air - Glass)) / ((Air + Glass) * (Air + Glass));

uniform mat4 transform;
uniform mat4 modelview;
uniform mat3 normalMatrix;

attribute vec4 vertex;
attribute vec3 normal;

varying vec3 v_reflection;
varying vec3 v_refraction;
varying float v_fresnel;

void main(void)
{
    // We calculate in world space.
    
    vec4 t_vertex = modelview * vertex;
    
    vec3 incident = normalize(vec3(t_vertex));

    // Assume incoming normal is normalized.
    vec3 t_normal = normalMatrix * normal;
    
    v_refraction = refract(incident, t_normal, Eta);
    v_reflection = reflect(incident, t_normal);
            
    // see http://en.wikipedia.org/wiki/Schlick's_approximation
    v_fresnel = R0 + (1.0 - R0) * pow((1.0 - dot(-incident, t_normal)), 5.0);
        
    gl_Position = transform * t_vertex;
}

And, finally, my fragment shader:


#version 120

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

uniform samplerCube cubemap;

varying vec3 v_refraction;
varying vec3 v_reflection;
varying float v_fresnel;

void main(void)
{
    vec4 refractionColor = textureCube(cubemap, normalize(v_refraction));
    vec4 reflectionColor = textureCube(cubemap, normalize(v_reflection));
        
    gl_FragColor = mix(refractionColor, reflectionColor, v_fresnel);
}

How I can make this work?

Answers

  • the glsl shaders tutorial here: https://processing.org/tutorials/pshader/ suggests that you need a #define somewhere to tell the renderer what type of shader you need.

    try changing line 36 to

    shader(shader, TEXLIGHT);
    

    we can't run your code without the textures so this is little more than a guess...

  • edited April 2016

    Thanks, @koogs!

    You are right, I put a #define PROCESSING_LIGHT_SHADER on my vertex shader to keep it right (but not seems to be a TEXLIGHT, because it isn't receiving any texture attribute from pipeline, so technically is just a light shader).

    But this is not the problem... :(

    About the textures, so sorry about that, I forget to provide it. here it is that I'm using, (but I think any cubemap can be used): https://drive.google.com/open?id=0B-KFG7c6SvVZVmY2MEFuZDBRa2s

  • processing version?

    (the PGL code differs depending on version)

  • edited April 2016

    Hi @koogs.

    Processing version is on topic title: 3.0. And as tagged on shader, I am using GLSL 1.20 (to be compatible on Android, the mode I am using to test).

  • actually, i'm not sure that's true for PGL, it is for GL, ie...

    // PGraphicsOpenGL 1.5.1
    GL gl = ((PGraphicsOpenGL)g).gl;
    // PJOGL 2.2.1, 30b7
    GL gl = ((PJOGL)beginPGL()).gl.getGL();
    

    but that's irrelevant...

    your code runs, but i see no sphere. i wonder if there's a way to check that the skybox has loaded correctly?

    and now i've broken the box too. 8(

Sign In or Register to comment.