Vertex Colour in a shader

Hi all,



I’ve been trying to work out how to get vertex colours into my shader. I know the colours are set right in the mesh as it works fine with unshaded - but in my shader I just see black.



As far as I could see the only thing in unshaded’s j3md is the option to turn on vertex colour. I couldn’t see anything that actually said to pass it in. In unshaded I see:



[java]attribute vec4 inColor;

[/java]

But I tried both that and

[java]in vec4 inColor;

[/java]

And I seemed to get nothing but blackness.



Any ideas what I’ve missed?



Thanks,

Z

Taken from unshaded.frag:

[java]

#ifdef HAS_VERTEXCOLOR

varying vec4 vertColor;

#endif

[/java]

1 Like

have you passed inColor from the vert to the frag?

Yes, I just don’t know how to tell the system to actually put the vertex colour into the variable. Does just giving it the magic name “vertColor” do the job?

[java]

uniform float g_Time;



uniform mat4 g_WorldViewProjectionMatrix;

uniform mat4 g_WorldMatrix;



varying vec4 vertColor;



in vec4 inPosition;



out vec4 texCoord4D;

out vec4 vertColour;



void main() {

// Vertex transformation

gl_Position = g_WorldViewProjectionMatrix * inPosition;

texCoord4D = g_WorldMatrix * inPosition;

vertColour = vertColor;

}

[/java]



[java]

MaterialDef VertexColourWrithe {



MaterialParameters {

Float Speed

Float Scale

}



Technique {

VertexShader GLSL100: Shaders/VertexColourWrithe.vert

FragmentShader GLSL100: Shaders/VertexColourWrithe.frag



WorldParameters {

Time

WorldViewProjectionMatrix

WorldMatrix

}

}



}



[/java]



[java]

#import "Shaders/SNoise4D.glsllib"



in vec4 texCoord4D;

in vec4 vertColour;



uniform float g_Time;

uniform float m_Speed;

uniform float m_Scale;





void main() {

gl_FragColor = vertColour;

}



[/java]



There it is so far…

@zarch said:
Yes, I just don't know how to tell the system to actually put the vertex colour into the variable. Does just giving it the magic name "vertColor" do the job?


Nope:

In the .vert
[java]
attribute vec4 inColor;
out vec4 vertColor;

main(){
vertColor=inColor;
}
[/java]

In the .frag
[java]
in vec4 vertColor;

main(){
gl_FragColor=vertColor;
}
[/java]
1 Like

That seems to have worked thanks, need to do some more testing tomorrow but it looks promising. :slight_smile:

[java]

uniform float g_Time;



uniform mat4 g_WorldViewProjectionMatrix;

uniform mat4 g_WorldMatrix;



out vec4 vertColor;

attribute vec4 inColor;

in vec4 inPosition;



out vec4 texCoord4D;

out vec4 vertColour;



void main() {

// Vertex transformation

gl_Position = g_WorldViewProjectionMatrix * inPosition;

texCoord4D = g_WorldMatrix * inPosition;

vertColour = inColor;

}

[/java]



[java]

MaterialDef VertexColourWrithe {



MaterialParameters {

Float Speed

Float Scale

}



Technique {

VertexShader GLSL100: Shaders/VertexColourWrithe.vert

FragmentShader GLSL100: Shaders/VertexColourWrithe.frag



WorldParameters {

Time

WorldViewProjectionMatrix

WorldMatrix

}

}



}



[/java]



[java]

#import "Shaders/SNoise4D.glsllib"



in vec4 texCoord4D;

in vec4 vertColour;



uniform float g_Time;

uniform float m_Speed;

uniform float m_Scale;





void main() {

gl_FragColor = vertColour;

}



[/java]





Should do,

btw, since i never saw a namig convention in shaders so i started my own.

I name my variables always with a prefix showing which shader writes it. It makes maybe no sense with only .vert and .frag, but using tessellation and geometry shader there are 5 shaders and i needed a orientation.



In this actual example i would name:





[java]

uniform float g_Time;



uniform mat4 g_WorldViewProjectionMatrix;

uniform mat4 g_WorldMatrix;





attribute vec4 inColor;

in vec4 inPosition;



out vec4 texCoord4D;

out vec4 vColor;



void main() {

// Vertex transformation

gl_Position = g_WorldViewProjectionMatrix * inPosition;

texCoord4D = g_WorldMatrix * inPosition;

vColor= inColor;

}

[/java]



[java]

MaterialDef VertexColourWrithe {



MaterialParameters {

Float Speed

Float Scale

}



Technique {

VertexShader GLSL100: Shaders/VertexColourWrithe.vert

FragmentShader GLSL100: Shaders/VertexColourWrithe.frag



WorldParameters {

Time

WorldViewProjectionMatrix

WorldMatrix

}

}



}



[/java]



[java]

#import "Shaders/SNoise4D.glsllib"



in vec4 texCoord4D;

in vec4 vColor;



uniform float g_Time;

uniform float m_Speed;

uniform float m_Scale;





void main() {

gl_FragColor = vColor;

}



[/java]

1 Like

Ok, I seem to have that working and I’ve moved onto the next problem. I need to pass in a Vector3 for each vertex that the renderer then uses (interpolated between as usual). Texture Coords seem to be V2 not V3 so I’ve gone with repurposing the Normal field for this (since my shader doesn’t need normals).



The V3 im passing in is not normalized (my shader won’t expect it to be) but I thought I’d quickly post to make sure I’m not opening myself up for future pain doing this :slight_smile:

Right, that all seems to work so unless anyone wants to warn me of any minefield I may have wondered into it’s looking pretty good :slight_smile:

Yeah, for some stuff it would be really nice if a mesh would be allowed to include custom data, similar to the user data on the node’s.

Hm you can definall all the vertex buffers you want and use them in your shaders?

@EmpirePhoenix said:
Hm you can definall all the vertex buffers you want and use them in your shaders?


How? When setting the buffers i can't i only use one of the Type's specified?
[java]
Mesh.setBuffer(Type.Position, 3, vertexBuffer);
[/java]

will get inPosition in my shader..

So how do i for example set a custom buffer and use them in a shader?

[java]
Mesh.setBuffer(Type.Movement,3, movementBuffer);
[/java]

Yeah, I guess the flexible way would be to have a String instead of an enum, then Type.Position becomes String Position = “inPosition” or whatever.



I don’t know if that’s even possible with opengl though?

Well you have like texcoord up to 8 or so? that should gi9ve plenty of room for own stuff.

Which is constrained to vec2…

Yes so ? if i need vec3 i just use two of them. You can emulate all datatypes with them easily, except doubles, but doubles on gpu makes no sense anyway.

@zarch said:
Which is constrained to vec2...


I was pretty sure that texture coords could be vec3 as long as you declare them that way on both ends. I may be remembering incorrectly.

You can use vec4, yeah.

Hmmm, the javadoc is out of date then (http://hub.jmonkeyengine.org/javadoc/com/jme3/scene/VertexBuffer.Type.html) as it specifically says 2 floats.



That’s useful to know though as while I don’t need it at the moment I might at some point :slight_smile: