We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpOpenGL and 3D Libraries › shaders in processing
Pages: 1 2 
shaders in processing (Read 17574 times)
shaders in processing
Sep 29th, 2006, 3:53am
 
Hi,

I'd like to know if someone has tried to incorporate shader support into processing (either Cg or GLSL).
I think it would be an interesting (besides cool and useful) project to work on, and I'm willing to do it. But first of all, it's good to know if something is already done (to avoid inventing the wheel twice, you know).
And from the experts, how difficult would this project be, given the current openGL rendering architecture of processing?

Thanks,
AC
Re: shaders in processing
Reply #1 - Sep 29th, 2006, 10:42am
 
GLSL is certainly possible, in fact I've written a class to handle everything for you.

It should be noted however, that if you use processing's OPENGL then some features maty behave oddly, as processing does some transforms in software, before they get handed over to OpenGL.

There's 2 two workaround to this, do: camera(0,0,0,0,0,-1,0,1,0);

And after that only do pur OpenGL work, e.g. no processing beginShape()/vertex() etc, only gl.glBeginShape()/g.glVertex3f() etc.

Or you could try the proGL library, this GLSL code should work with it, but its untested.

Code:
class GLSL
{
int programObject;
GL gl;
boolean vertexShaderEnabled;
boolean vertexShaderSupported;
int vs;
int fs;

GLSL()
{
gl=((PGraphicsGL)g).gl;
String extensions = gl.glGetString(GL.GL_EXTENSIONS);
vertexShaderSupported = extensions.indexOf("GL_ARB_vertex_shader") != -1;
vertexShaderEnabled = true;
programObject = gl.glCreateProgramObjectARB();
vs=-1;
fs=-1;
}

void loadVertexShader(String file)
{
String shaderSource=join(loadStrings(file),"\n");
vs = gl.glCreateShaderObjectARB(GL.GL_VERTEX_SHADER_ARB);
gl.glShaderSourceARB(vs, 1, new String[]{shaderSource},(int[]) null, 0);
gl.glCompileShaderARB(vs);
checkLogInfo(gl, vs);
gl.glAttachObjectARB(programObject, vs);
}

void loadFragmentShader(String file)
{
String shaderSource=join(loadStrings(file),"\n");
fs = gl.glCreateShaderObjectARB(GL.GL_FRAGMENT_SHADER_ARB);
gl.glShaderSourceARB(fs, 1, new String[]{shaderSource},(int[]) null, 0);
gl.glCompileShaderARB(fs);
checkLogInfo(gl, fs);
gl.glAttachObjectARB(programObject, fs);
}

int getAttribLocation(String name)
{
return(gl.glGetAttribLocationARB(programObject,name));
}

int getUniformLocation(String name)
{
return(gl.glGetUniformLocationARB(programObject,name));
}

void useShaders()
{
gl.glLinkProgramARB(programObject);
gl.glValidateProgramARB(programObject);
checkLogInfo(gl, programObject);
}

void startShader()
{
gl.glUseProgramObjectARB(programObject);
}

void endShader()
{
gl.glUseProgramObjectARB(0);
}

void checkLogInfo(GL gl, int obj)
{
IntBuffer iVal = BufferUtil.newIntBuffer(1);
gl.glGetObjectParameterivARB(obj, GL.GL_OBJECT_INFO_LOG_LENGTH_ARB, iVal);

int length = iVal.get();
if (length <= 1)
{
return;
}
ByteBuffer infoLog = BufferUtil.newByteBuffer(length);
iVal.flip();
gl.glGetInfoLogARB(obj, length, iVal, infoLog);
byte[] infoBytes = new byte[length];
infoLog.get(infoBytes);
println("GLSL Validation >> " + new String(infoBytes));
}
}


Usage:
Code:
GLSL glsl;

void setup()
{
// normal stuff, size, gl=((PGraphicsGL)g).gl etc..
glsl=new GLSL();
glsl.loadVertexShader("MyShader.vert");
glsl.loadFragmentShader("MyShader.frag");
glsl.useShaders();
}

void draw()
{
//stuff unrelated to drawing...
//draw initial stuff that doens't need the shader.
glsl.startShader();
//draw things that you want the shader applied to
glsl.endShader();
// draw things that you don't want the shader applied to.
}


If you have a really complex scene, and want multiple shaders, you can just create more than one GLSL object, and startShader/endShader as and when needed.
Re: shaders in processing
Reply #2 - Sep 29th, 2006, 5:30pm
 
Many thanks for the info and the code!

Actually, I was looking forward to write something like your GLSL class (in fact, it is very similar to stuff that I wrote to handle glsl and cg shaders in my own c++ programs). So, I'll start by trying your class...
Re: shaders in processing
Reply #3 - Oct 2nd, 2006, 6:30pm
 
i just cleaned up the shader handling in gestalt.
an examples would look something like this:

Code:
import gestalt.Gestalt;
import gestalt.candidates.glsl.ShaderManager;
import gestalt.candidates.glsl.ShaderProgram;
import gestalt.p5.GestaltPlugIn;

import processing.opengl.PGraphicsOpenGL;


GestaltPlugIn gestalt;

ShaderManager _myShaderManager;

ShaderProgram _myShaderProgram;

float[][] _mySpherePosition;

float _myRotation;

void setup() {
/* setup p5 */
size(640, 480, OPENGL);
sphereDetail(4);
noStroke();

gestalt = new GestaltPlugIn(this);

/* setup shader */
_myShaderManager = gestalt.drawablefactory().extensions().shadermanager();
_myShaderManager.init( ( (PGraphicsOpenGL) g).gl, ( (PGraphicsOpenGL) g).glu);

_myShaderProgram = _myShaderManager.createShaderProgram();
_myShaderManager.attachVertexShader(_myShaderProgram, loadStrings("toon.vsh"));
_myShaderManager.attachFragmentShader(_myShaderProgram, loadStrings("toon.fsh"));
gestalt.bin(Gestalt.BIN_FRAME_SETUP).add(_myShaderManager);

_myShaderManager.enable(_myShaderProgram);
_myShaderManager.setUniform(_myShaderProgram, "thresholds", new float[] {
0.1f, 0.2f, 0.5f, 0.95f }
);

/* create sphere positions */
_mySpherePosition = new float[1000][4];
for (int i = 0; i < _mySpherePosition.length; i++) {
_mySpherePosition[i][0] = random(width);
_mySpherePosition[i][1] = random(height);
_mySpherePosition[i][2] = random( -10, 10);
_mySpherePosition[i][3] = random(10, 20);
}
}


void draw() {
background(64, 64, 64);

float myX = (mouseX / (float) width - 0.5f) * 2.0f;
float myY = (mouseY / (float) height - 0.5f) * 2.0f;
directionalLight(255, 255, 255, myX, myY, 1);

translate(width / 2, height / 2);
_myRotation += 0.03f;
rotateX(sin(_myRotation) * 0.1f);
rotateY(cos(_myRotation * 0.65f) * 0.1f);
translate(width / -2, height / -2);

for (int i = 0; i < _mySpherePosition.length; i++) {
pushMatrix();
translate(_mySpherePosition[i][0], _mySpherePosition[i][1], _mySpherePosition[i][2]);
sphere(_mySpherePosition[i][3]);
popMatrix();
}
}

Re: shaders in processing
Reply #4 - Oct 3rd, 2006, 12:27am
 
Using the GLSL class, the program starts running but it throws lots of runtime exceptions (starting with "java.lang.VerifyError: class processing.core.PGraphics3 overrides final method [].[]")
I will begin debugging and see how it goes...
Re: shaders in processing
Reply #5 - Oct 3rd, 2006, 11:29am
 
Ah, the GLSL thing was written pre-0116 which changed the names slightly, try changing the line:

gl=((PGraphicsGL)g).gl;

to

gl=((PGraphicsOpenGL)g).gl;
Re: shaders in processing
Reply #6 - Oct 3rd, 2006, 2:26pm
 
Yeah, I changed that already, and I also added the imports needed to have buffer support.
But the exceptions happen anyways... I'll work on it in the next couple of days.
Re: shaders in processing
Reply #7 - Oct 4th, 2006, 1:47pm
 
I forgot to change PGraphicsGL by PGraphicsOpenGL (I think I did but somehow I ended up using the old class name in my last test program)...

It works fine now. I tried a minimal shader (only gl_Position = ftransform() in the vertex shader, gl_FragColor = vec4(1.0,0.0,0.0,1.0) in the fragment shader), and as expected, all I get is a red screen.
Re: shaders in processing
Reply #8 - Oct 6th, 2006, 4:32pm
 
I was looking at the jogl and jogl-demos websites, and seems that all is needed to have support also for CG shaders is to import com.sun.opengl.cg !!

Now I'll try to write a class for handling CG shaders, similar to the GLSL class.
Re: shaders in processing
Reply #9 - Oct 7th, 2006, 6:41am
 
I finished a class to handle Cg shaders in processing. Here it is:

Code:

import com.sun.opengl.cg.*;
import javax.media.opengl.*;
import com.sun.opengl.util.*;
import java.nio.*;
import processing.opengl.*;

class CG
{
GL gl;
boolean vertexShaderSupported;
boolean fragmentShaderSupported;
boolean vertexShaderEnabled;
boolean fragmentShaderEnabled;
CGcontext context;
CGprogram vertexProgram;
CGprogram fragmentProgram;
int vertexProfile;
int fragmentProfile;

CG()
{
gl = ((PGraphicsOpenGL)g).gl;
String extensions = gl.glGetString(GL.GL_EXTENSIONS);
vertexShaderSupported = extensions.indexOf("GL_ARB_vertex_shader") != -1;
fragmentShaderSupported = extensions.indexOf("GL_ARB_fragment_shader") != -1;

context = CgGL.cgCreateContext();

vertexProfile = CgGL.cgGLGetLatestProfile(CgGL.CG_GL_VERTEX);
if (vertexProfile == CgGL.CG_PROFILE_UNKNOWN) println("Vertex profile could not be created");
else CgGL.cgGLSetOptimalOptions(vertexProfile);

fragmentProfile = CgGL.cgGLGetLatestProfile(CgGL.CG_GL_FRAGMENT);
if (fragmentProfile == CgGL.CG_PROFILE_UNKNOWN) println("Fragment profile could not be created");
else CgGL.cgGLSetOptimalOptions(fragmentProfile);

vertexProgram = null;
fragmentProgram = null;
}

void loadVertexShader(String file)
{
String shaderSource = join(loadStrings(file), "\n");
vertexProgram = CgGL.cgCreateProgram(context, CgGL.CG_SOURCE, shaderSource, vertexProfile, null, null);
checkErrorInfo(file, vertexProgram);
vertexShaderEnabled = (vertexProgram != null) && (vertexProfile != CgGL.CG_PROFILE_UNKNOWN);
}

void loadFragmentShader(String file)
{
String shaderSource = join(loadStrings(file), "\n");
fragmentProgram = CgGL.cgCreateProgram(context, CgGL.CG_SOURCE, shaderSource, fragmentProfile, null, null);
checkErrorInfo(file, fragmentProgram);
fragmentShaderEnabled = (fragmentProgram != null) && (fragmentProfile != CgGL.CG_PROFILE_UNKNOWN);
}

CGparameter getVertParameter(String name)
{
return CgGL.cgGetNamedParameter(vertexProgram, name);
}

CGparameter getFragParameter(String name)
{
return CgGL.cgGetNamedParameter(fragmentProgram, name);
}

void useShaders()
{
if (vertexShaderEnabled) CgGL.cgGLLoadProgram(vertexProgram);
if (fragmentShaderEnabled) CgGL.cgGLLoadProgram(fragmentProgram);
}

void startShader()
{
if (vertexShaderEnabled)
{
CgGL.cgGLBindProgram(vertexProgram);
CgGL.cgGLEnableProfile(vertexProfile);
}
if (fragmentShaderEnabled)
{
CgGL.cgGLBindProgram(fragmentProgram);
CgGL.cgGLEnableProfile(fragmentProfile);
}
}

void endShader()
{
if (vertexShaderEnabled) CgGL.cgGLDisableProfile(vertexProfile);
if (fragmentShaderEnabled) CgGL.cgGLDisableProfile(fragmentProfile);
}

void checkErrorInfo(String fn, CGprogram program)
{
if (program == null)
{
int error = CgGL.cgGetError();
println("Cg error(s) in " + fn);
println(CgGL.cgGetErrorString(error));
println(CgGL.cgGetLastListing(context));
}
}
}


An example of usage:

Code:

CG cg;

void setup()
{
size(400, 400, OPENGL);

cg = new CG();
cg.loadVertexShader("MyShader.vert");
cg.loadFragmentShader("MyShader.frag");
cg.useShaders();
}

void draw()
{
//stuff unrelated to drawing...
//draw initial stuff that doens't need the shader.
cg.startShader();

// Cg programs need the OpenGL modelview projection matrix.
CgGL.cgGLSetStateMatrixParameter(cg.getVertParameter("ModelViewProj"),
CgGL.CG_GL_MODELVIEW_PROJECTION_MATRIX,
CgGL.CG_GL_MATRIX_IDENTITY);

//draw things that you want the shader applied to
quad(0, 0, 0, 400, 400, 400, 400, 0);
cg.endShader();
// draw things that you don't want the shader applied to.
}


with the following vertex shader:

Code:

void main(float4 Position : POSITION,
out float4 HPosition: POSITION,
uniform float4x4 ModelViewProj)
{
HPosition = mul(ModelViewProj, Position);
}


and fragment shader:

Code:

float4 main() : COLOR
{
return float4(1.0, 0.0, 0.0, 1.0);
}


Re: shaders in processing
Reply #10 - Oct 17th, 2006, 1:05pm
 
Has anyone passed a dynamic texture into a GLSL fragment shader?
glTexImage2D seems to be throwing a wobbly, the last parameter should be byte array but processing is expecting a long, expanding on the GLSL example posted above. I've found many java examples which seem okay, I'm trying to port working C++ code.
Re: shaders in processing
Reply #11 - Oct 17th, 2006, 4:19pm
 
Just to let you know, I have done it, and it's fairly simple, especially if you use the JOGL Texture class, but it's at home, so I'll not be able to dig it up until later today.
Re: shaders in processing
Reply #12 - Oct 17th, 2006, 7:37pm
 
In setup:
Code:
  tex0=loadImage("img.png");
tex1=loadImage("bump.png");

gl.glGenTextures(2,tex,0);
gl.glBindTexture(GL.GL_TEXTURE_2D,tex[0]);
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, 4,tex0.width, tex0.height,
0, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE,
IntBuffer.wrap(tex0.pixels));
gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR);
// Linear Filtering
gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR);
// Linear Filtering
gl.glBindTexture(GL.GL_TEXTURE_2D,tex[1]);
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, 4,tex1.width, tex1.height,
0, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE,
IntBuffer.wrap(tex1.pixels));
gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR);
// Linear Filtering
gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR);
// Linear Filtering

shaderimgloc[0]=glsl.getUniformLocation("Base");
shaderimgloc[1]=glsl.getUniformLocation("NormalHeight");



In draw:
Code:
  gl.glActiveTexture(GL.GL_TEXTURE0+2);
gl.glBindTexture(GL.GL_TEXTURE_2D, tex[0]);
gl.glActiveTexture(GL.GL_TEXTURE0+1);
gl.glBindTexture(GL.GL_TEXTURE_2D, tex[1]);

gl.glUniform1i(shaderimgloc[0],2);
gl.glUniform1i(shaderimgloc[1],1);


You pass the texture to the shader via a TextureID in a uniform variable

I think there's a nicer way with the JOGL Texture helper, and it'd be something like:

Code:

Texture tex0=TextureIO.newTexture(new File(dataPath("img.png")),true);
Texture tex1=tex=TextureIO.newTexture(new File(dataPath("bump.png")),true);

shaderimgloc[0]=glsl.getUniformLocation("Base");
shaderimgloc[1]=glsl.getUniformLocation("NormalHeight");


Code:
tex0.enable();
tex1.enable();

gl.glActiveTexture(GL.GL_TEXTURE0+2);
tex0.bind();
gl.glActiveTexture(GL.GL_TEXTURE0+1);
tex1.bind();

gl.glUniform1i(shaderimgloc[0],2);
gl.glUniform1i(shaderimgloc[1],1);


Re: shaders in processing
Reply #13 - Oct 20th, 2006, 1:04pm
 
Thanks, it was the +1 and the +2 which I was getting wrong consistently.. thanks
if(tex1!=-1)
 {
 //  texture (work);
   glsl.gl.glActiveTexture(glsl.gl.GL_TEXTURE0+2);
 glsl.gl.glBindTexture(glsl.gl.GL_TEXTURE_2D,glsl.gl.GL_TEXTURE0+2);
   glsl.gl.glUniform1iARB(tex1,1);
 
 }
if(tex2!=-1)
 {
glsl.gl.glActiveTexture(glsl.gl.GL_TEXTURE0+1);
glsl.gl.glBindTexture(glsl.gl.GL_TEXTURE_2D,glsl.gl.GL_TEXTURE0+1);  
   glsl.gl.glUniform1iARB(tex2,0);
 
 }
Re: shaders in processing
Reply #14 - Feb 29th, 2008, 2:28am
 
The info posted here has been amazingly useful - thanks to everyone, especially JohnG, for this. However, I'm still at the learning stage and am struggling.

What I would like to ask is if anyone has a complete set of working code, to achieve, for example bump-mapping:

i.e. the main sketch, as well as shader code - to post as an example of how to successfully string everything together? (i.e. binding textures etc.)

The class definitions for both Cg and GLSL posted on this forum have been very enlightening, and I have basic texturing working in Cg . But as regards multi-texturing, bump mapping, etc. I'm just wondering if anyone might have a basic, complete functional example, as a guide/starting-point?

I'm falling down between the principles and the practice, here.
Pages: 1 2