www.jpct.net

jPCT-AE - a 3d engine for Android => Support => Topic started by: zoalord12 on November 19, 2015, 09:14:36 pm

Title: Object3D color not being read in shader
Post by: zoalord12 on November 19, 2015, 09:14:36 pm
Hi all,

Reading an Object3D,
when i render it as it is , the "green" color shows up on the mesh since its coming from the material file, (I loaded from an .obj + .mtl)

When I add a shader, I cant get the correct vertex color in my attribute variable.
The normals come through fine though, using this method.
PLEASE HELP. thanks in advance



// VERTEX SHADER   -----------------------------------------------------------------------

attribute vec4 additionalColor;

attribute vec4 position;
attribute vec3 normal;
attribute vec4 color;

uniform mat4 modelViewMatrix;
uniform mat4 modelViewProjectionMatrix;

varying vec4 myColor;
void main(void)
{

  myColor = color;

  // I also tried this one but neither one works.
  myColor = additionalColor;

  gl_Position = modelViewProjectionMatrix * position;
}


// FRAGMENT SHADER  ------------------------------------------------------------------

precision mediump float;
varying vec4 myColor;

void main ()
{
   gl_FragColor = vec4(myColor.xyz, 1);
}





Title: Re: Object3D color not being read in shader
Post by: EgonOlsen on November 19, 2015, 09:31:50 pm
additionalColor has to be a uniform, not an attribute. Attributes change for each vertex, uniforms don't.
Title: Re: Object3D color not being read in shader
Post by: zoalord12 on November 19, 2015, 09:55:02 pm
Hmm ok,  but the material color coming from the .mtl file is not for the whole mesh
there can be "n" number of materials each being a solid color, one for the arm, one for the feet, one for the head etc.

so it should come through the color channel.
I now understand that I can set additional color (only 1 RGB ) for the mesh, so that was my mistake asking about that in the previous question.

but my question is why am I not getting the color channel for my mesh using
attribute vec3 color in the shader ?
Title: Re: Object3D color not being read in shader
Post by: zoalord12 on November 19, 2015, 09:59:27 pm
Here is the example : The color output on the mesh is BLACK.

When i don't use the shader, color of mesh = green which it should be
When i have something like this myObject3D.add(myShader) , i get color = black.

// --- THIS IS THE SUBSET OF MY MTL FILE ------------------------------------------------------

newmtl torsoColor
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.296990 0.451769 0.032732
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000

// ----------------------------------------------------------------------


// ----- VERTEX


attribute vec4 position;
attribute vec4 color;

varying vec4 myColor;
void main(void)
{
             myColor = color ;


    gl_Position = modelViewProjectionMatrix * position;
}

// --------------- FRAGMENT

varying vec4 myColor;
void main ()
{

 gl_FragColor = vec4(myColor.xyz, 1);

}
Title: Re: Object3D color not being read in shader
Post by: EgonOlsen on November 19, 2015, 11:03:48 pm
Not sure what you mean. additionalColor has to be a uniform. If it's not, it won't be injected. additionalColor is the value set by http://www.jpct.net/jpct-ae/doc/com/threed/jpct/Object3D.html#setAdditionalColor(int, int, int) (http://www.jpct.net/jpct-ae/doc/com/threed/jpct/Object3D.html#setAdditionalColor(int, int, int)). It has nothing to do with the material color. jPCT-AE doesn't really know the concept of material colors, so the loader mimics them by creating textures in that color. If you want to change these colors, you have to modify the textures. Have a look at the log output when loading the model. It will tell you if it's creates a unicolored texture for this purpose.
Title: Re: Object3D color not being read in shader
Post by: zoalord12 on November 19, 2015, 11:09:40 pm
Oh i see,

found this : http://www.jpct.net/forum2/index.php?topic=4139.5;wap2

Where you explain it. I just used texture0 and it works now.
I was confused since I didn't attach any textures but you explan in there that a new texture is generated. 


Can you share those few lines of code where the color from float/double is read from the .mtl file and written to the texture. I want to write something like this


// ORIGINAL MTL FILE

newmtl torsoColor
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.296990 0.451769 0.032732

// ---------------------


//  IN THE SHADER I WANT

vec4 color == GET THE COLOR AT THE VERTEX.

if (color.x == 0.296990  && color.y == 0.451769 && color.z ==   0.032732)  {


}

// ------------------------------------

or any other way you recommend doing this since my model is color coded ... like hand = shade of red, face = shade of green etc..




Title: Re: Object3D color not being read in shader
Post by: zoalord12 on November 20, 2015, 07:33:07 am
can you also tell me what happens when there are multiple materials ? like for instance this case


//---------------------------------

 Blender MTL File: 'free_car_1_b.blend'
# Material Count: 6

newmtl bodyMat
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.005056 0.000000 0.050252
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2

newmtl glassMat
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2

newmtl metalMat1
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2

newmtl metalMat2
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.000000 0.000000 0.000000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
 ... and so on


Title: Re: Object3D color not being read in shader
Post by: EgonOlsen on November 20, 2015, 08:33:44 am
If there are multiple materials (which define a diffuse color and no texture), multiple colored textures will be created and the polygons in question will be mapped accordingly. If you then want to change the textures, you can't use setTexture() anymore but he PolygonManager instead.

Regarding reading in the color information: Just split the line and parse the floats. It's really simple stuff.
Title: Re: Object3D color not being read in shader
Post by: zoalord12 on November 20, 2015, 03:45:23 pm
Thanks for that info, it makes things a lot clearer.

One more thing, so if i have lets say 20 diffuse materials, i get 20 textures ,
but i cant access them directly in the shader , since I only have access to the 4 textures in the shader ( textureUnit0 -  textureUnit3), is that correct ?


AFTER CHECKING:
Texturemanager , does a replacement based on name, not ID, I see that the texturecount is 5, while my diffuse material count is 6
 also they have no names or do they have the material name, i dont know ?
i tried a texture lookup using the material name but it didnt work.


Regarding replacing textures at runtime, can i just do

texture abc = tm.gettextureById(id)
abc = new texture .. ... or use a scaled bitmap etc.

How can i change the textures with just the id, and not knowing the name ?


Title: Re: Object3D color not being read in shader
Post by: EgonOlsen on November 20, 2015, 04:11:30 pm
They have a artifical name based on the color. You should see it the log output. Or, if that's not the case, you can get all names from the TextureManager. Just look at them and you'll notice the naming convention.

To make you better understand the texture/shader relation, here is what happens behind the scenes:

For each diffuse color in a material, a texture with that color will be created (if the material doesn't contain a texture anyway). It will create one Object3D with x different textures assigned to different polygons depending on the materials of those. However, that's not what's getting rendered. Because of the way in which graphics hardware works, you can't render one mesh with different textures on different polygons. So what actually happens is, that jPCT-AE internally splits the object into lumps of polygons, one for each texture/color. You should be able to spot that in the log output as well (some "compiled" message). Each of these lumps will be rendered in its own draw call with its own set of textures (in your case one on the first stage). So in your shader, you have one texture only, but your shader will be used in multiple render calls.

May I ask what exactly you want to create? Maybe there's another solution...
Title: Re: Object3D color not being read in shader
Post by: zoalord12 on November 20, 2015, 04:34:56 pm

oh i see, i looked through the debugger its _obj-Color:R/G/B

my logger keeps flooding the console with "Binding texture 0" and "Binding texture 1", even with LL_ERRORS_ONLY
so I cant even see these messages.

I'm building a model viewer where you can change colors for certain parts on the fly, as in using user input.
The model is color coded in the sense that certain mesh parts are one specific color, so im just using crude logic to identify the color,
and use if statements inside the shader to change it to user color, if existing color is within a certain tolerance range.


I now see that the texture swapping solution will be way more elegant.

Also, im assuming if there is any material in the file that is not being used will not be TEXTURED, right ?
that would explain why my total texture count is less than the number of materials in the .mtl file



BTW, your engine is the best I've seen for android. I was able to get it up and running in 1 day. I use AndEngine but its only good for 2D stuff.
Thank you so much for writing this.



here is a sample


// Changing COLORS AT RUNTIME IN THE FRAG SHADER

// If "check" is within a certain tolerance, then we have the correct color that must be replaced.
// "check" is being read from the texture, and compared to the known RGB color "x"

// x is the known value of the color which must be replaced.

bool isWithin(float check, float x, float tol) {
   if(  (check >= (x - tol)) &&
        (check <=(x + tol)))
        return true;
    return false;
}


void main () {
    vec4 printCol;
    vec4 base = texture2D(textureUnit0, TEX0);

    if (isWithin(base.x, mod1.x, modTol) && isWithin(base.y, mod1.y, modTol) && isWithin(base.z, mod1.z, modTol) )
        printCol = vec4(mod1NewColor.xyz, 1);
    else
        printCol = vec4(base.xyz, 1);// myAddColor;// * diffuse;// vDiffuse;

   
    gl_FragColor = printCol;
}
Title: Re: Object3D color not being read in shader
Post by: EgonOlsen on November 20, 2015, 05:17:08 pm
my logger keeps flooding the console with "Binding texture 0" and "Binding texture 1", even with LL_ERRORS_ONLY
so I cant even see these messages.
That can't happen. This message is printed out only in one part of the code. That part is conditional. It only gets executed, if the log level is set to DEBUG. Check you log level settings...maybe you are setting it to DEBUG somewhere else.

I now see that the texture swapping solution will be way more elegant.
I think so. Either that, or you can use an ITextureEffect implementation to change the color of the existing texture. This causes a new texture upload for each change in color, but these textures are pretty small, so it might not be an issue.

Also, im assuming if there is any material in the file that is not being used will not be TEXTURED, right ?
that would explain why my total texture count is less than the number of materials in the .mtl file
Yes, it does it on demand only.

Another thing to keep in mind is that you can't split the model afterwards, i.e. if your color code for polygon 1 and 2 is x and for polygons 3,4 and 5 y, you can modify 1 and 2 and 3,4,5 but you can't set 3 and 4 to z and keep 5 at y...if you know what I mean... ;)

About the shader solution: That should work as well. I seems a little hacky to me though, but maybe that's just me.

Title: Re: Object3D color not being read in shader
Post by: EgonOlsen on November 20, 2015, 05:31:53 pm
Another idea would be an implementation of IRenderHook. The beforeRendering-method will be called before each draw call. It gets the current polygonID as parameter. If you know which id corresponds to which color, you can write a much simpler shader that takes a single uniform set inside this method that defines the final color.
Title: Re: Object3D color not being read in shader
Post by: zoalord12 on November 20, 2015, 06:40:03 pm
That shader is very very hacky and totally not scalable, but helped me prototype things i do after the color changes   ^_^

I haven't seen any samples with the IRenderHook, so i didn't take that route.

Option-1
From what i know now, i can use the setTexture and keep creating these 16x16 textures with a flat color.

Option-2
This IRenderHook thing will be way faster, but i dont know how to get started with this, can you point me to a sample because I want to use this if possible.
My polygons dont have IDs, I'm assuming by ID you mean HAND, FACE etc for the polygons representing hand/face , correct ?


BTW, is there any change I can get access to the MTL reader, or any way to access the material RGB and Titles ?
Currently, I'm using OBJImport alongside your api to read the materials separately. Would be nice to get this done in 1 place.
Title: Re: Object3D color not being read in shader
Post by: EgonOlsen on November 20, 2015, 08:39:05 pm
The polygonID is basically a polygon index. You just to figure out which one is which.

About the IRenderHook: Just implement it and do your magic in the beforeRendering()-method. To execute it, set it to all Object3D instances in question. That's it! The method will be called automatically before each draw call.
Title: Re: Object3D color not being read in shader
Post by: EgonOlsen on November 20, 2015, 08:42:18 pm
About the material loader. It's really simple stuff (mtl is a String that contains the mtl-file's content as text):

Code: [Select]
                Map<String, Object[]> mats = new HashMap<String, Object[]>();
StringTokenizer st = new StringTokenizer(mtl, "\n");
String matName = null;
RGBColor col = null;
String texture = null;
String texture2 = null;
float[] cols = new float[3];
boolean next = true;
String line = null;
Float trans = null;

TextureManager texMan = TextureManager.getInstance();

int mode = 0;
while (st.hasMoreTokens()) {
if (next) {
line = st.nextToken().trim();
}
switch (mode) {
case (0): {
if (line.startsWith("newmtl ")) {
matName = line.substring(7).trim();
mode = 1;
next = true;
col = null;
texture = null;
trans = null;
Logger.log("Processing new material " + matName + "!", Logger.MESSAGE);
}
break;
}
case (1): {
String lLine = line.toLowerCase();
if (lLine.startsWith("kd ")) {
String sub = lLine.substring(3).trim();
StringTokenizer st2 = new StringTokenizer(sub, " ");
int ind = 0;
while (st2.hasMoreTokens() && ind < 3) {
String c = st2.nextToken();
try {
cols[ind] = Float.valueOf(c).floatValue();
} catch (Exception e) {
cols[ind] = 1;
Logger.log("Error in MTL-file near: " + line, Logger.ERROR);
}
ind++;
}
col = new RGBColor((int) (cols[0] * 255f), (int) (cols[1] * 255f), (int) (cols[2] * 255f));
} else {
if ((lLine.startsWith("map_kd") || lLine.startsWith("map_ka")) && line.length() > 7) {
// Textur
if (lLine.startsWith("map_kd")) {
texture = removeBogusData(line.substring(7).trim());
if (!texMan.containsTexture(texture)) {
texMan.addTexture(texture);
Logger.log("Texture named " + texture + " added to TextureManager!", Logger.MESSAGE);
}
} else {
texture2 = removeBogusData(line.substring(7).trim());
if (!texMan.containsTexture(texture2)) {
texMan.addTexture(texture2);
Logger.log("Texture named " + texture2 + " added to TextureManager!", Logger.MESSAGE);
}
}
} else {
if (lLine.startsWith("d ")) {
float tt = -1;
try {
tt = Float.parseFloat(line.substring(2).trim());
} catch (Exception e) {
}
if (tt != -1 && tt != 1) {
trans = Float.valueOf(tt);
}
} else {
if (lLine.startsWith("newmtl")) {
mode = 0;
next = false;
}
}
}
}
break;
}
}
if (!next || !st.hasMoreTokens()) {
mats.put(matName, new Object[] { col, texture, trans });
}
}
Title: Re: Object3D color not being read in shader
Post by: zoalord12 on November 23, 2015, 03:52:54 pm
Thanks EgonOlsen, with your help i was able to get the required results for my project :)
Title: Re: Object3D color not being read in shader
Post by: zoalord12 on November 24, 2015, 10:48:06 pm
More shower thoughts ...

I'm thinking about replacing the .mtl file flat colors with an unwrapped texture, 1 for each model.
So lets say im using a single texture for a model,,, its unwrapped UV on a flat texture with different colors/patterns whatever,

Now, is it possible to tag the vertices of the face, hand etc. in some way to help me figure out later what vertices belong to what texture ?

like i want to write this in my code

model.getSUBPART("FACE").setTexture( myNewFaceTexture);




Title: Re: Object3D color not being read in shader
Post by: EgonOlsen on November 24, 2015, 10:53:19 pm
You can query the PolygonManager about polygon textures. However, and I'm not sure if I got this correctly, you can't assign individual textures to polygons than didn't have individual textures before. So you can't create an Object3D with 20 polygons that uses one texture and assign the first 10 polygon texture x and the second 10 polygon texture y, if that's what you have in mind...
Title: Re: Object3D color not being read in shader
Post by: zoalord12 on November 24, 2015, 11:51:28 pm
yeah no i got that part. all polygons will be textured initially.
once they are textured with the default color in the texture, now i want to change the textures.


Hmmm correct me here please,

 i think i need to save each material as a separate jpg, as in i cant get by using something like this

https://drive.google.com/file/d/0BzkvMWM-w80JT3JkWDNSZGVMVDQ/view?usp=sharing (https://drive.google.com/file/d/0BzkvMWM-w80JT3JkWDNSZGVMVDQ/view?usp=sharing)
since i assume the texture space is all shared hence the texturemanager will create only 1 texture.
Title: Re: Object3D color not being read in shader
Post by: EgonOlsen on November 25, 2015, 12:39:33 pm
In that case, it's one texture. Depending on your needs, you might get away with a custom shader to modify the coloring of some parts. I've described the method that I'm using in my RPG here briefly: http://www.jpct.net/forum2/index.php/topic,2471.msg26829.html#msg26829 (http://www.jpct.net/forum2/index.php/topic,2471.msg26829.html#msg26829)
Title: Re: Object3D color not being read in shader
Post by: zoalord12 on November 26, 2015, 12:00:46 am
hmmm yeah i do get these color maps with some models. look like a good first solution, but i think its hacky

I mean there is a limitation on the number of materials you can represent this way right ? but thanks, i think doing my shader is the first step
so will get on that
Title: Re: Object3D color not being read in shader
Post by: EgonOlsen on November 26, 2015, 06:57:38 am
I don't see what's hacky with that. It just blends pixels based on some blending map. It doesn't rely on exact color values and it even allows for smooth transitions. You can create the color map on your own in any image editor that supports layers. It's just a variation of the usual texture splatting approach.
Title: Re: Object3D color not being read in shader
Post by: zoalord12 on December 02, 2015, 03:35:42 pm
oh i meant hacky as in its not that diverse
you can only represent a few number of materials this way, what if you want to differentiate , say 20 materials on the character
then the masking wont work, if i understand it correctly
Title: Re: Object3D color not being read in shader
Post by: EgonOlsen on December 02, 2015, 04:06:13 pm
oh i meant hacky as in its not that diverse
you can only represent a few number of materials this way, what if you want to differentiate , say 20 materials on the character
then the masking wont work, if i understand it correctly
...that's right...unless you revert to being hacky again and do some magic with color ranges instead of the actual colors... ;)