Object3D's transparency issue

Started by AeroShark333, December 06, 2014, 12:07:56 PM

Previous topic - Next topic

AeroShark333

#30
It was using OpenGL 2 yes
I am 100% sure I am using OpenGL2 since the beginning.

Sorry for the misinterpretation by the way

EgonOlsen

Try this fragment shader instead:


precision mediump float;

uniform sampler2D textureUnit0;
uniform sampler2D textureUnit1;
uniform sampler2D textureUnit2;
uniform sampler2D textureUnit3;

uniform int textureCount;
uniform int blendingMode[4];

varying vec2 texCoord[4];
varying vec4 vertexColor;
varying float fogWeight;
varying vec3 fogVertexColor;

const vec4 WHITE = vec4(1,1,1,1);

void main() {
vec4 col = texture2D(textureUnit0, texCoord[0]) * vertexColor;
if (col.a < 0.5) {
discard;
} else {
if (textureCount>1) {

// Can't index texture samplers and switch doesn't seem to compile(?)...end result:

int mode=blendingMode[1];
vec2 texCo=texCoord[1];

if (mode==0) {
// Modulate
col *= texture2D(textureUnit1, texCo);
} else if (mode==1) {
// Add
col += texture2D(textureUnit1, texCo);
} else if (mode==3) {
// Blend
col *= (WHITE - texture2D(textureUnit1, texCo));
} else if (mode==2) {
// Replace
col = texture2D(textureUnit1, texCo);
} else if (mode==4) {
// Decal
vec4 col2=texture2D(textureUnit1, texCo);
col = vec4(mix(col.rgb, col2.rgb, col2.a), col2.a);
}

if (textureCount>2) {

mode=blendingMode[2];
texCo=texCoord[2];

if (mode==0) {
// Modulate
col *= texture2D(textureUnit2, texCo);
} else if (mode==1) {
// Add
col += texture2D(textureUnit2, texCo);
} else if (mode==3) {
// Blend
col *= (WHITE - texture2D(textureUnit2, texCo));
} else if (mode==2) {
// Replace
col = texture2D(textureUnit2, texCo);
} else if (mode==4) {
// Decal
vec4 col2=texture2D(textureUnit2, texCo);
col = vec4(mix(col.rgb, col2.rgb, col2.a), col2.a);
}

if (textureCount>3) {

mode=blendingMode[3];
texCo=texCoord[3];

if (mode==0) {
// Modulate
col *= texture2D(textureUnit3, texCo);
} else if (mode==1) {
// Add
col += texture2D(textureUnit3, texCo);
} else if (mode==3) {
// Blend
col *= (WHITE - texture2D(textureUnit3, texCo));
} else if (mode==2) {
// Replace
col = texture2D(textureUnit3, texCo);
} else if (mode==4) {
// Decal
vec4 col2=texture2D(textureUnit3, texCo);
col = vec4(mix(col.rgb, col2.rgb, col2.a), col2.a);
}
}
}
}

if (fogWeight>-0.9) {
col.xyz = (1.0-fogWeight) * col.xyz + fogVertexColor;
}
}

gl_FragColor=col;
}


There are known issues with the discard; on PowerVR GPUs. So i put the actual calculations in an additional else branch. Maybe that helps. If not, then it's getting harder. You actually need access to such a device to debug it properly. Shaders can be real pain, because even correct code can be "optimized" to complete rubbish by some shader compilers. That's why jPCT-AE's default shaders contain such strange hacks at times.

EgonOlsen

I've added it to the projects page.

AeroShark333

Thanks for adding it to the projectlist!

Some bad news from the user, the new fragment shader does not work... :(

EgonOlsen

I'm almost out of ideas then. This is the exact same shader code that jPCT's default shader uses except for the additional discard. The only option left (without access to a device) is to make all textures square and hope for the best...

AeroShark333

No luck with the textures square as well :(
Are there any other options?
Perhaps similar/alternative code that does the same as
discard;? (I don't think 'return;' would solve it.

EgonOlsen

It might be worth a try. Everything is.

You might as well try to move the discard/return down like here:


precision mediump float;

uniform sampler2D textureUnit0;
uniform sampler2D textureUnit1;
uniform sampler2D textureUnit2;
uniform sampler2D textureUnit3;

uniform int textureCount;
uniform int blendingMode[4];

varying vec2 texCoord[4];
varying vec4 vertexColor;
varying float fogWeight;
varying vec3 fogVertexColor;

const vec4 WHITE = vec4(1,1,1,1);

void main() {
vec4 col = texture2D(textureUnit0, texCoord[0]) * vertexColor;

if (textureCount>1) {

// Can't index texture samplers and switch doesn't seem to compile(?)...end result:

int mode=blendingMode[1];
vec2 texCo=texCoord[1];

if (mode==0) {
// Modulate
col *= texture2D(textureUnit1, texCo);
} else if (mode==1) {
// Add
col += texture2D(textureUnit1, texCo);
} else if (mode==3) {
// Blend
col *= (WHITE - texture2D(textureUnit1, texCo));
} else if (mode==2) {
// Replace
col = texture2D(textureUnit1, texCo);
} else if (mode==4) {
// Decal
vec4 col2=texture2D(textureUnit1, texCo);
col = vec4(mix(col.rgb, col2.rgb, col2.a), col2.a);
}

if (textureCount>2) {

mode=blendingMode[2];
texCo=texCoord[2];

if (mode==0) {
// Modulate
col *= texture2D(textureUnit2, texCo);
} else if (mode==1) {
// Add
col += texture2D(textureUnit2, texCo);
} else if (mode==3) {
// Blend
col *= (WHITE - texture2D(textureUnit2, texCo));
} else if (mode==2) {
// Replace
col = texture2D(textureUnit2, texCo);
} else if (mode==4) {
// Decal
vec4 col2=texture2D(textureUnit2, texCo);
col = vec4(mix(col.rgb, col2.rgb, col2.a), col2.a);
}

if (textureCount>3) {

mode=blendingMode[3];
texCo=texCoord[3];

if (mode==0) {
// Modulate
col *= texture2D(textureUnit3, texCo);
} else if (mode==1) {
// Add
col += texture2D(textureUnit3, texCo);
} else if (mode==3) {
// Blend
col *= (WHITE - texture2D(textureUnit3, texCo));
} else if (mode==2) {
// Replace
col = texture2D(textureUnit3, texCo);
} else if (mode==4) {
// Decal
vec4 col2=texture2D(textureUnit3, texCo);
col = vec4(mix(col.rgb, col2.rgb, col2.a), col2.a);
}
}
}
}

if (fogWeight>-0.9) {
col.xyz = (1.0-fogWeight) * col.xyz + fogVertexColor;
}


if (col.a < 0.5) {
discard;
}
gl_FragColor=col;
//if (col.a < 0.5) {
// discard;
//}
}


...either before or after the gl_FragColor...

It might also be worth a try to replace the "precision mediump float;" by "precision highp float;" in the first line. All of this doesn't actually make sense...but anyway. Abother idea is to remove the discard completely. Maybe we a re looking at the problem from the wrong side. Maybe the shader itself is the problem and not the discard...

AeroShark333

#37
Okay I tried a few things.
1. discard before gl_FragColor
2. discard after gl_FragColor
3. Option 1 + highp
4. Option 2 + highp
5. The shader code by Lobby without discard

Apparently none worked, so the problem is not the discard (I think)

EgonOlsen

#38
...either that, or your updated versions won't get executed on the actual device. Can you somehow confirm that your changes really make it onto the device? If you remove the discard, the resulting shader is the normal default shader that jPCT-AE uses and i'm not aware of any problems with that. Also, please make sure that you are calling build() on all of your Object3Ds.

However, there are other, simpler default shaders. We could try to modify one of them. But for choosing one, i have to know which features you are actually using. So...


  • Are you using light sources or just ambient lighting?
  • If you are using lights, how many?
  • Are you using fog?

AeroShark333

Quote from: EgonOlsen on January 09, 2015, 05:46:40 PM
...either that, or your updated versions won't get executed on the actual device. Can you somehow confirm that your changes really make it onto the device? If you remove the discard, the resulting shader is the normal default shader that jPCT-AE uses and i'm not aware of any problems with that. Also, please make sure that you are calling build() on all of your Object3Ds.

However, there are other, simpler default shaders. We could try to modify one of them. But for choosing one, i have to know which features you are actually using. So...


  • Are you using light sources or just ambient lighting?
  • If you are using lights, how many?
  • Are you using fog?

package com.aeroshark333.skinviewer.skinparts;

import com.threed.jpct.GLSLShader;
import com.threed.jpct.Object3D;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.TextureManager;

public class Body extends Object3D {

private static final long serialVersionUID = 8216608860877707087L;

public Body(final GLSLShader shader) {

super(12);

final Object3D box = this;

SimpleVector upperLeftFront = new SimpleVector(-1, -1.5f, -0.5f);
SimpleVector upperRightFront = new SimpleVector(1, -1.5f, -0.5f);
SimpleVector lowerLeftFront = new SimpleVector(-1, 1.5f, -0.5f);
SimpleVector lowerRightFront = new SimpleVector(1, 1.5f, -0.5f);

SimpleVector upperLeftBack = new SimpleVector(-1, -1.5f, 0.5f);
SimpleVector upperRightBack = new SimpleVector(1, -1.5f, 0.5f);
SimpleVector lowerLeftBack = new SimpleVector(-1, 1.5f, 0.5f);
SimpleVector lowerRightBack = new SimpleVector(1, 1.5f, 0.5f);

// Front
box.addTriangle(upperLeftFront, 0, 0, lowerLeftFront, 0, 1,
upperRightFront, 1, 0, TextureManager.getInstance()
.getTextureID("bodyfront"));
box.addTriangle(upperRightFront, 1, 0, lowerLeftFront, 0, 1,
lowerRightFront, 1, 1, TextureManager.getInstance()
.getTextureID("bodyfront"));
// Back
box.addTriangle(upperLeftBack, 0, 0, upperRightBack, 1, 0,
lowerLeftBack, 0, 1,
TextureManager.getInstance().getTextureID("bodyback"));
box.addTriangle(upperRightBack, 1, 0, lowerRightBack, 1, 1,
lowerLeftBack, 0, 1,
TextureManager.getInstance().getTextureID("bodyback"));
// Top
box.addTriangle(upperLeftBack, 0, 0, upperLeftFront, 0, 1,
upperRightBack, 1, 0, TextureManager.getInstance()
.getTextureID("bodytop"));
box.addTriangle(upperRightBack, 1, 0, upperLeftFront, 0, 1,
upperRightFront, 1, 1, TextureManager.getInstance()
.getTextureID("bodytop"));
// Bottom
box.addTriangle(lowerLeftBack, 0, 0, lowerRightBack, 1, 0,
lowerLeftFront, 0, 1, TextureManager.getInstance()
.getTextureID("bodybottom"));
box.addTriangle(lowerRightBack, 1, 0, lowerRightFront, 1, 1,
lowerLeftFront, 0, 1, TextureManager.getInstance()
.getTextureID("bodybottom"));
// Right
box.addTriangle(upperLeftFront, 0, 0, upperLeftBack, 1, 0,
lowerLeftFront, 0, 1, TextureManager.getInstance()
.getTextureID("bodyright"));
box.addTriangle(upperLeftBack, 1, 0, lowerLeftBack, 1, 1,
lowerLeftFront, 0, 1, TextureManager.getInstance()
.getTextureID("bodyright"));
// Left
box.addTriangle(upperRightFront, 0, 0, lowerRightFront, 0, 1,
upperRightBack, 1, 0, TextureManager.getInstance()
.getTextureID("bodyleft"));
box.addTriangle(upperRightBack, 1, 0, lowerRightFront, 0, 1,
lowerRightBack, 1, 1, TextureManager.getInstance()
.getTextureID("bodyleft"));

box.setName("body");
this.setTransparency(-1);
this.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
this.setShader(shader);
this.compile();
this.strip();
box.build();
}
}

This code is okay right?


  • Are you using light sources or just ambient lighting?
  • Just ambient lighting
  • If you are using lights, how many?
  • One, the ambient lighting
  • Are you using fog?
  • No.

this.mainWorld.setAmbientLight(255, 255, 255);


Well... I gave him an .apk file with the custom shader not set to the right leg.
That DID show him the right leg properly.

EgonOlsen

Yes, that code looks fine. It confuses me a little that "this" and box are actually the same instance, but anyway.

If you are using ambient only, no fog and only one texture layer (...are you?), try these shaders instead:

Vertex:

uniform mat4 modelViewProjectionMatrix;

uniform vec4 additionalColor;
uniform vec4 ambientColor;

uniform float alpha;
uniform bool useColors;

attribute vec4 position;
attribute vec3 normal;
attribute vec4 color;
attribute vec2 texture0;

varying vec2 texCoord;
varying vec4 vertexColor;

const vec4 WHITE = vec4(1,1,1,1);

void main() {
texCoord = texture0;
vec4 pos = position;
vec3 normalDummy = normal;

vertexColor=vec4(min(WHITE, ambientColor + additionalColor).xyz, alpha);

if (useColors) {
vertexColor *= color;
}

gl_Position = modelViewProjectionMatrix * pos;
}



Fragment:

precision highp float;

uniform sampler2D textureUnit0;

varying vec2 texCoord;
varying vec4 vertexColor;

void main() {
gl_FragColor= texture2D(textureUnit0, texCoord) * vertexColor;
        if (gl_FragColor.a<0.5) {
           discard;
        }
}

AeroShark333

You sir, are an hero!
The shader worked for him (as well for me)
Thanks so much :D

Yeah... I should have kept using either box# or this# and not both... It does not really look neat at the moment.

And correct, I am only using ambient lighting, no fog and one texturelayer per object.

Thanks for your time, input and fast responses :)
I hope not to have wasted your time... If so, I am sorry.

EgonOlsen

No, it wasn't a waste of time. It's an indication that the fully blown default shader doesn't work on all devices if not all the features that it offers are used. And while that's not a real problem because it doesn't happen in real life, it's not supposed to happen. That shader is supposed to work fine even if not all of it's features are being used. I'll have a look at the engine's code to see if i can spot the problem.

EgonOlsen

Can't find anything that's fishy with the shader or the way in which it's being initialized. I tried to reproduce the problem on my only PowerVR based device, but i can't. Everything works just fine. Until i know any better, i consider this problem to be a bug in the shader compiler on that particular device. It wouldn't be the first one of that kind that darkens everything. Case closed  for now...

AeroShark333

Hmm, okay! Thanks for the help. (it happened on just one device, I guess the user is unlucky then...)

A new stacktrace:
java.lang.NullPointerException: Attempt to invoke virtual method 'int com.threed.jpct.Texture.getOpenGLID(int)' on a null object reference
at com.threed.jpct.GLRenderer.setTextures(GLRenderer.java:2441)
at com.threed.jpct.GLRenderer.drawVertexArray(GLRenderer.java:2297)
at com.threed.jpct.World.draw(World.java:1417)
at com.threed.jpct.World.draw(World.java:1100)
at com.aeroshark333.skinviewer.SkinActivity$ViewerRenderer.onDrawFrame(SkinActivity.java:1659)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1531)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1248)


line #1659
mainWorld.draw(frameBuffer);

Amount of reports: 1
Android: 5.0
Device: Samsung Galaxy S5

As far as I know... I am not messing with Object textures...