Shaders and uv maps

Hi.

I’m trying to get some shaders applied to my models, with various results.

First, i grabbed most of the stuff from TestNormalMap.java to get something up and running, but my uv coordinates seemed to get messed up, while some of the shader effects worked.



I then read about tangents and binormals in this thread: http://www.jmonkeyengine.com/forum/index.php?topic=3467.0

and modified the shader to take that as input (calculating them using “TangentBinormalGenerator”)

I then pass this to the shader like this:


FloatBuffer binormal = mesh.getBinormalBuffer();
FloatBuffer tangent = mesh.getTangentBuffer();
so.setAttributePointer("modelTangent", 3, false, 0, tangent);
so.setAttributePointer("modelBinormal", 3, false, 0, binormal);



Now, either i still get messed up uv coords on my static objects, or a crash sometimes, and always a crash on my SkinNode
This is the crash:

org.lwjgl.opengl.OpenGLException: Cannot use Buffers when Array Buffer Object is enabled
at org.lwjgl.opengl.GLChecks.ensureArrayVBOdisabled(GLChecks.java:90)
at org.lwjgl.opengl.ARBVertexProgram.glVertexAttribPointerARB(ARBVertexProgram.java:175)
at com.jme.scene.state.lwjgl.shader.LWJGLShaderUtil.updateShaderAttribute(LWJGLShaderUtil.java:249)



Any ideas how to proceed?

Thanks!

if you pm me the model i can check it in scene worker…

i have normal map shader support and tangent and binormal attribute generation scripted in the app…

it's working for all the models i used it on…

You got mail, thanks.



Just for reference, here's my .vert shader. It's based on one i found on the forum (sorry, can't reference), but have modified it slightly (basically, the tangent and binormal stuff were commented out)


attribute vec3 modelTangent;
attribute vec3 modelBinormal;

varying vec3 viewDirection;
varying vec3 lightDirection;

void main(void)
{
   /* Transform vertices and pass on texture coordinates */
   gl_Position = ftransform();
   gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0 * vec4(4.0, 4.0, 1.0, 1.0);
   
   /* Transform vertex into viewspace */
   vec4 vertexViewSpace = gl_ModelViewMatrix * gl_Vertex;
   
   /* Get view and light directions in viewspace */
   vec3 localViewDirection = -vertexViewSpace.xyz;
   vec3 localLightDirection = gl_LightSource[0].position.xyz;
   
   /* Calculate tangent info - stored in colorbuffer */
//   vec3 normal = gl_NormalMatrix * gl_Normal;
//   vec3 tangent = gl_NormalMatrix * (gl_Color.xyz*2.0-1.0);
//   vec3 binormal = cross( normal, tangent );

   /* Calculate tangent info - stored in attributes */
   vec3 normal = gl_NormalMatrix * gl_Normal;
   vec3 tangent = gl_NormalMatrix * modelTangent;
   vec3 binormal = gl_NormalMatrix * modelBinormal;

   /* Calculate tangent info - stored in texturecoordinates */
//   vec3 normal = gl_NormalMatrix * gl_Normal;
//   vec3 tangent = gl_NormalMatrix * gl_MultiTexCoord1.xyz;
//   vec3 binormal = gl_NormalMatrix * gl_MultiTexCoord2.xyz;
   
   /* Transform localViewDirection into texture space */
   viewDirection.x = dot( tangent, localViewDirection );
   viewDirection.y = dot( binormal, localViewDirection );
   viewDirection.z = dot( normal, localViewDirection );

   /* Transform localLightDirection into texture space */
   lightDirection.x = dot( tangent, localLightDirection );
   lightDirection.y = dot( binormal, localLightDirection );
   lightDirection.z = dot( normal, localLightDirection );
}


here is the shader i use…

looks pretty much the same as yours…



attribute vec3 modelTangent;
attribute vec3 modelBinormal;

varying vec3 viewDirection;
varying vec3 lightDirection;

void main(void)
{
   /* Transform vertices and pass on texture coordinates */
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
   gl_TexCoord[0] = gl_MultiTexCoord0;
   
   /* Transform vertex into viewspace */
   vec4 vertexViewSpace = gl_ModelViewMatrix * gl_Vertex;
   
   /* Get view and light directions in viewspace */
   vec3 localViewDirection = -vertexViewSpace.xyz;
   vec3 localLightDirection = gl_LightSource[0].position.xyz;
   
   /* Calculate tangent info - stored in colorbuffer */
   /*vec3 normal = gl_NormalMatrix * gl_Normal;
   vec3 tangent = gl_NormalMatrix * (gl_Color.xyz * 2.0 -1.0);
   vec3 binormal = cross( normal, tangent );*/
   
   /* Calculate tangent info - stored in attributes */
   vec3 normal = gl_NormalMatrix * gl_Normal;
   vec3 tangent = gl_NormalMatrix * modelTangent;
   vec3 binormal = gl_NormalMatrix * modelBinormal;

   /* Transform localViewDirection into texture space */
   viewDirection.x = dot( tangent, localViewDirection );
   viewDirection.y = dot( binormal, localViewDirection );
   viewDirection.z = dot( normal, localViewDirection );

   /* Transform localLightDirection into texture space */
   lightDirection.x = dot( tangent, localLightDirection );
   lightDirection.y = dot( binormal, localLightDirection );
   lightDirection.z = dot( normal, localLightDirection );
}

Still having problems with the shaders. Ncomp tested the model in Sceneworker, which worked fine, and the shaders are identical, so we can rule them out. Binormals and tangents are calculated using the framework, so that shouldn't be the problem either. That leaves how i apply it. I think i've tried every possible combination, but here's the current implementation:


so.load(this.getClass()
                        .getClassLoader()
                        .getResource(
                                        "Shaders/normalmap.vert"),
                this.getClass()
                        .getClassLoader()
                        .getResource(
                                        "Shaders/normalmap.frag"));
                so.apply();

                so.setUniform("baseMap", 0);
                so.setUniform("normalMap", 1);
                so.setUniform("specularMap", 2);
                so.setEnabled(true);



After this i apply the shader to the mesh.
Then in update() :

FloatBuffer binormal = mesh.getBinormalBuffer();
FloatBuffer tangent = mesh.getTangentBuffer();
so.setAttributePointer("modelTangent", 3, false, 0, tangent);
so.setAttributePointer("modelBinormal", 3, false, 0, binormal);



The error message makes me think i must somehow lock the buffer. Or could it possibly be a threading issue?

Update: Nah, shouldn't be threading..

Thanks

how are you creating the buffers?

I call

TangentBinormalGenerator.generate(model);

as i load the meshes.

that is weird…

try applying the shader…

then calculating the tangent buffers…

then assigning them as attributes…

org.lwjgl.opengl.OpenGLException: Cannot use Buffers when Array Buffer Object is enabled


jME2 doesn't support generic vertex attributes with VBO. Either put your vertex attributes inside the color/texcoord buffers or don't use VBO. Or, alternatively, you can use jME3 which supports normal mapping natively, uses generic vertex attributes with VBO & shaders by default.

ncomp:

No luck there either.



Momoko:

Aha. I'm learning as i go along. jME3 sure sounds sweet. I'm just afraid i'll lose alot of functionality that's not yet been developed for it. I'll take a closer look at it, aswell as see if i can use your solution to the problem.



Thanks

can you try it in scene worker…

i can give you a number of steps to set it up…

Will do. I'll download the source as well and see how it sets up the shaders. Can't promise i'll have time to do it tonight though, but i'll try.


there is a new standalone build up in the downloads section…

download this…

launch the .bat file…

right click on root node…

import your model…

add a new renderstate->glslshaderobjectsstate to the model…

add a new texture state…

load the textures to it…

select the shader state…

open the shader editor…

from the snippets menu select normal map shader…

edit the uniforms to use the correct textures…

compile and update…

then select the mesh…

from the utils menu select execute beanshell script on object…

from the snippets menu select tangent calculation…

execute that…

and see if that works…



might sound like alot of steps but it's pretty straightforward…

if you want i can do this up as a video tutorial…

i share your pain with attributes…

drove me half mental the first time i tried doing it…

Thanks ncomp, I appreciate your help. Works like a charm in SceneWorker (although the textures need some tweaking).



Update: Although the normal map seems inverted (light/dark) on some faces. What's up with that?

Finally some progress.



Momoko's suggested method did not stop the crashes, alone, so i decided to backtrack and check everything from the beginning again.



I had just glanced at the shader ncomp posted and didn't notice the difference at first. However, the first two lines are very different. Replacing the ones in my shader stopped the crash, and fixed the texture (it was scaled down 4 times).



Now i have an ugly looking normal map and horrible performance! Time for some tweaking :wink:



Thanks again.

Hello again.

I have a new question on the same subject (well, maybe uv maps is a bit off)



Background:

I have set up a couple of base shaders, which i apply to SharedMeshes when loading them. These SharedMeshes are instanced during startup of the game.



The issue is that when i rotate them 90 degrees, the shaders become black. I assume this has something to do with the normals changing, but i'm not sure.

I've tried reapplying the shader after rotating, calculating new binormals and tangents., to no avail.



Is this something that sounds familiar? Is it a problem with the instances, the fact that i send the VBO's through texcoords (do they become inverted when rotating?), or something i haven't thought of (i've tried every form of .update on the model).



Thanks