Introducing Pixel and Vertex Shaders

Tada ;D
Ok so I’ve spent a great deal of time trying to implement those features that I wished were available with Java3D.
After countless trials, I’ve got them implemented somehow, meaning that I’m positive Yuri or David could come up with an even better approach.
The reason why I needed them Pixel and Vertex Shaders is the overhead caused by repeated calls to native functions that Xith3D as well as any java binding outthere causes.
To demonstrate the huge benefits of VertexShaders, I wrote a little shader coder for NeHe’s celshading tutorial.
You need to hit space to have the model moving and notice how good the vertex shaded demo runs: That’s right, on my machine it’s 3X faster than the conventional demo.
I attached the source code for the PS and VS as well as the demo.
Enjoy fellas :stuck_out_tongue:
PS: Hi Yuri ;D

Nehe’s Cel-Shading Tutorial (Without VS)

http://www.users.xith.org/JavaCoolDude/JWS/Nehe/Lesson37/Lesson37icon.jpg

Keys: Space, 1,2, Up, Down
Source

Nehe’s Cel-Shading Tutorial (With VS)

http://www.users.xith.org/JavaCoolDude/JWS/Nehe/Lesson37VS/Lesson37icon.jpg

Keys: Space, 1,2, Up, Down
Source

PS & VS classes


!!ARBvp1.0

ATTRIB OriginalPos                = vertex.position;
ATTRIB TmpNormal                  = vertex.normal;

PARAM lightAngle                  =   program.env[0];
PARAM ModelViewProj[4]            = { state.matrix.mvp };
PARAM ModelViewInvertTranspose[4] = { state.matrix.modelview.invtrans};

TEMP TmpVector;   
TEMP TmpShade;
TEMP temp;
  
DP3  TmpVector.x, TmpNormal, ModelViewInvertTranspose[0];
DP3  TmpVector.y, TmpNormal, ModelViewInvertTranspose[1];
DP3  TmpVector.z, TmpNormal, ModelViewInvertTranspose[2];

DP3  TmpVector.w, TmpVector, TmpVector;
RSQ  TmpVector.w, TmpVector.w;
MUL  TmpVector  , TmpVector, TmpVector.w;

DP3  TmpShade.x, TmpVector , lightAngle;      
MAX  TmpShade.x, TmpShade.x, 0.0;

DP4 temp.x, ModelViewProj[0], OriginalPos;
DP4 temp.y, ModelViewProj[1], OriginalPos;
DP4 temp.z, ModelViewProj[2], OriginalPos;
DP4 temp.w, ModelViewProj[3], OriginalPos;

MOV result.position     , temp;
MOV result.color        , vertex.color;
MOV result.texcoord[0].x, TmpShade.x;

END

A possible improvement would be the creation of a ShaderProgramState class that can bind a vertex and a pixel shader at the same time (spelling?), because with my current approach, I made it possible for one shader Program per Appearance to run at a time :’(

Very cool work! So would this work on only a subset of cards or driver versions or manufacterers? It sounds like the application would need to know if was going to use the vertex program (if available) or fall back to more traditional methods. Perhaps we need to expose the capabilities of the card to the application?

You got me there man, I should have written a little function to check for GL_VERTEX_PROGRAM and GL_FRAGMENT_PROGRAM extensions which should be available on any DirectX 8.0 compatible card.
But like I said this is just an attempt at doing Vertex and Pixel shading in a Xith3D application :slight_smile:

Sigh… how should I start telling how miserable I am at this moment :-/
So a little while ago I got VS to work with NeHe’s Lesson 37 as well as my own PerPixel lighting demo (where I tricked the card into taking the tangent and binormal as colors and normals’ parameters ;D ), but then I realized the limits of my implementation since only one ShaderProgram could run at once whereas best effects can be achieved in a combination of PS and VS.
So I modified the Appearance class in the following way


    /**
     * Set the vertex shader information.
     */
    public final void setVertexShaderProgram(VertexProgram vertexPro) {
        this.vertexPro =  vertexPro;
        setChanged(true);
    }

    /**
     * Set the Fragment shader information.
     */
    public final void setFragmentShaderProgram(FragmentProgram fragmentPro) {
        this.fragmentPro =  fragmentPro;
        setChanged(true);
    }

and followed the steps of David Y in implementing the TextureShader/Peer.
Now I bumped into a problem, and so far it’s kicking me hard in the nuts.
See this is how OpenGL would normally expect to handle things.

Enable PS|VS
Bind PS|VS
Set PS|VS parameters (Optional)
Draw Geometry
Disable PS|VS.

In the way I implemented the PS and VS, something must be going wrong since troubleshooting revealed that what’s going is

Bind PS
Disable PS
Bind VS
Disable VS

Which doesn’t follow the regular trend of doing things in OpenGL
(Bind PS
Bind VS


Disable PS
Disable VS)

So anyways, here’s a link to what I’ve done so far, I guess David or Yuri would spend very little time fixing what I’ve unconsiously screwed up.
Please

Great work!

I will test this ASAP, because of I want to make it working with NV_vertex_program extension, too, because of it failed to run on GeF 440 Go with old drivers from Toshiba (no update available), while other vertex programming tests work.

Yuri

The GeForce4Mx series of cards DO NOT support standard Pixel and Vertex shaders known as Fragment and Vertex program.
On the other hand they do include support for Nv_Vertex_Program and registry combiners which are specific to Nvidia.
Of course not all of us own Nvidia hardware
ATi forever <3

Yes, I know. But also MX series with drivers higher than 44xx support at least ARB_vertex_program extension, so vertex programs should be able to run also there.

Actually, that’s why I was voting for Cg, but anyway all possibilities should be available.

Yuri

I’m sorry if I ever sound like an arrogant ass but I will again state that the Nvidia Geforce MX series do neither support GL_VERTEX_PROGRAM, nor GL_FRAGMENT_PROGRAM commonly know as Vertex and Pixel shaders.
Using Geforce 4 as a name for the MX series is indeed misleading as it implies that the hardware is DirectX 8.0 compliant just like the Ti series are, whereas it only supports DirectX 7.0 specifications along side with few manufacturer’s proper extensions (registry combiners…)

:slight_smile:

Pretty much all drivers will support vertex programs via software emulation if the hardware doesn’t support them. You might not get as good performance (what with having to chuck data back and forth on the AGP) but it’ll work.

Software emulation pffffffft :stuck_out_tongue:

Anyways I’m wicked happy to announce that I not only figured what the hell was wrong with my implementation of the said VS and PS, but I also fixed it.
Let me upload the new version that:
Doesn’t leak to other shape3Ds in the scene.
Doesn’t necessarily require parameters to be passed in, as a matter a fact, only the shader code string is stricly required for the effects to show up.
Fragment and Vertex Programs could be attached to an appearance at once for more spectacular effects.
Let me see if I can get a Phong/Blinn illumination demo working by tonight.
/me runs away crying in all happiness

;D

Source

This what I changed to get this version up and working properly:

In ShapeAtomPeer, right towards the end of the function “bindGeometryComponent(GL gl, CanvasPeer canvas, GeomData data, int arrayType)”, I added:


        gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB);
        gl.glDisable(GL.GL_VERTEX_PROGRAM_ARB);
        ProfileTimer.endProfile();

A possible improvement that I might do is checking in the first run whetheir the current hardware supports GL.GL_FRAGMENT_PROGRAM_ARB & GL.GL_VERTEX_PROGRAM_ARB, if not there is no point in disabling them (Application might even crash, sigh).

Check the following classes to get to know how VS and PS work:
Main shader class
PS
VS

Example:


    modelAppearance.setVertexShaderProgram(  new VertexProgram(getShaderCode("Data/celshading.jcd")));
    modelAppearance.setFragmentShaderProgram(new FragmentProgram(getShaderCode("Data/ps.jcd")));

Where getShaderCode(String filename) is a function to retrieve code from a file :slight_smile:

Well as you can see everything works just fine, but I’m having some trouble setting up my camera class which uses a robot to set the mouse coordinates back to the exact center of the canvas; in fact it always comes with a ~30 pixels offset on the y axis and a lot less than that on the x axis.
I figured it would be the JFrame title bar’s size as well as the borders’ (genius ;D) but till now I have no clue on how to get the exact size of the mentioned parts.
Any help?

http://www.users.xith.org/JavaCoolDude/Pictures/phong.jpg

In an AWT Frame call getInsets() to get the info. It has properties bottom, top, etc, for the size of the border…

It must be called after showing the window, before that the insets are all 0.

Rafael