Texture doesn't work, all black except skybox

recently, we've been working on a small game application. and i found that my texture state on terrain block(as well as other TriMesh) doesn't work. It's all black after the scene is loaded. strange thing is, the skybox rendered well.



hope someone could help me slove this hot potato.



here is the core code:


public class Game extends BaseGame {
   protected void initGame() {
      // Create the box
      Box b = new Box("MyBox", new Vector3f(640, 150, 2000), 20, 20, 20);
      b.setModelBound(new BoundingBox());
      b.updateModelBound();

      // Create a texture
      TextureState ts = DisplaySystem.getDisplaySystem().getRenderer()
            .createTextureState();
      Texture t = TextureManager.loadTexture(Skybox.class.getClassLoader()
            .getResource("netjava/robo3d/resource/image/skyNorth.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
      ts.setTexture(t);
      b.setRenderState(ts);
      
      scene = new Node("root");
      scene.updateRenderState();
      
      scene.attachChild(b);
   }
   ...
}


You say that the sky box is rendering correctly but "terrain block (as well as other TriMesh)" is not, yet you provide only the code for your sky box setup.  How 'bout sending some code that shows what is not working?

blaine said:

You say that the sky box is rendering correctly but "terrain block (as well as other TriMesh)" is not, yet you provide only the code for your sky box setup.  How 'bout sending some code that shows what is not working?


thank you for you reminding.
to make it simpler, i only pasted the key code. here the complete code:

1.class Game:


import java.util.logging.Level;
import java.util.logging.Logger;

import netjava.robo3d.scene.Scene;

import com.jme.app.BaseGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.InputHandler;
import com.jme.input.action.InputActionEvent;
import com.jme.input.action.InputActionInterface;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.Skybox;
import com.jme.scene.shape.Box;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.TextureManager;
import com.jme.util.Timer;

public class Game extends BaseGame {

   private Logger logger = Logger.getLogger(Game.class.getName());

   private Camera cam;
   private Timer timer;
   private InputHandler input;
   
   private int width;
   private int height;
   private int depth;
   private int freq;
   private boolean fullscreen;

   private Scene scene;

   public static void main(String[] args) {
      Game game = new Game();

      game.setConfigShowMode(ConfigShowMode.AlwaysShow, Game.class
            .getClassLoader().getResource(
                  "netjava/robo3d/resource/image/splash.jpg"));

      Logger.getLogger("").setLevel(Level.ALL);

      game.start();
   }

   @Override
   protected void initSystem() {
      width = settings.getWidth();
      height = settings.getHeight();
      depth = settings.getDepth();
      freq = settings.getFrequency();
      fullscreen = settings.isFullscreen();

      try {
         this.display = super.display;
         display = DisplaySystem.getDisplaySystem(settings.getRenderer());
         display.createWindow(width, height, depth, freq, fullscreen);

         cam = display.getRenderer().createCamera(width, height);
      } catch (JmeException e) {
         logger.log(Level.SEVERE, "Could not create displaySystem", e);
         System.exit(1);
      }
      display.setTitle("Robo3D v2.0");

      display.getRenderer().setBackgroundColor(ColorRGBA.black.clone());

      cam.setFrustumPerspective(45.0f, (float) width / (float) height, 1,
            5000);
      Vector3f loc = new Vector3f(640.0f, 150.0f, 2560.0f);
      Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);
      Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
      Vector3f dir = new Vector3f(0.0f, 0.0f, -1.0f);
      // Move our camera to a correct place and orientation.
      cam.setFrame(loc, left, up, dir);
      cam.update();

      display.getRenderer().setCamera(cam);

      timer = Timer.getTimer();
   }

   @Override
   protected void initGame() {
      input = new KeyboardHandler();
      input.addAction(new InputActionInterface() {
         public void performAction(InputActionEvent evt) {
            Game.this.finished = true;
         }
      }, "exit", false);
      
      scene = new Scene(input);
   }

   @Override
   protected void update(float interpolation) {
      timer.update();
      interpolation = timer.getTimePerFrame();

      input.update(interpolation);
      scene.update(interpolation);
   }

   @Override
   protected void render(float interpolation) {
      // Clear the screen
      display.getRenderer().clearBuffers();
      display.getRenderer().draw(scene);
   }

   @Override
   protected void reinit() {
      display.recreateWindow(width, height, depth, freq, fullscreen);
   }

   @Override
   protected void cleanup() {
   }
}



2.class Scene


import java.util.ArrayList;
import java.util.List;

import netjava.robo3d.tank.Player;
import netjava.robo3d.tank.Robot;

import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.image.Texture.MagnificationFilter;
import com.jme.image.Texture.MinificationFilter;
import com.jme.input.ChaseCamera;
import com.jme.input.InputHandler;
import com.jme.light.DirectionalLight;
import com.jme.light.Light;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.Skybox;
import com.jme.scene.shape.Box;
import com.jme.scene.state.CullState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jme.util.geom.BufferUtils;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.util.MidPointHeightMap;

public class Scene extends Node {

   private static final long serialVersionUID = 427189480039821532L;

   private Player player;
   private List<Robot> robots = new ArrayList<Robot>();

   private Skybox sky;
   private TerrainBlock tb;

   private DisplaySystem display;
   private InputHandler input;

   private Camera cam;
   private ChaseCamera chaser;

   private Light light;

   public Scene(InputHandler input) {
      this.setName("scene");
      this.display = DisplaySystem.getDisplaySystem();
      this.input = input;
      this.cam = display.getRenderer().getCamera();

      
      createSkybox();

      setModelBound(new BoundingBox());
      updateWorldBound();
      
      createTerrainBlock();

      lightWorld();

      // update the scene graph for rendering
      updateGeometricState(0.0f, true);
      updateRenderState();
   }

   private void lightWorld() {
      light = new DirectionalLight();
      LightState lightState = display.getRenderer().createLightState();
      lightState.setEnabled(true);
      lightState.detachAll();
      lightState.attach(light);
      this.setRenderState(lightState);
   }

   private void createSkybox() {
      sky = new Skybox("sky", 5000, 5000, 5000);

      Texture north = TextureManager.loadTexture(Skybox.class
            .getClassLoader().getResource(
                  "netjava/robo3d/resource/image/skyNorth.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
      Texture south = TextureManager.loadTexture(Skybox.class
            .getClassLoader().getResource(
                  "netjava/robo3d/resource/image/skySouth.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
      Texture east = TextureManager.loadTexture(Skybox.class.getClassLoader()
            .getResource("netjava/robo3d/resource/image/skyEast.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
      Texture west = TextureManager.loadTexture(Skybox.class.getClassLoader()
            .getResource("netjava/robo3d/resource/image/skyWest.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
      Texture up = TextureManager.loadTexture(Skybox.class.getClassLoader()
            .getResource("netjava/robo3d/resource/image/skyClouds.png"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
      Texture down = TextureManager.loadTexture(Skybox.class.getClassLoader()
            .getResource("netjava/robo3d/resource/image/skyBottom.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);

      sky.setTexture(Skybox.Face.North, north);
      sky.setTexture(Skybox.Face.West, west);
      sky.setTexture(Skybox.Face.South, south);
      sky.setTexture(Skybox.Face.East, east);
      sky.setTexture(Skybox.Face.Up, up);
      sky.setTexture(Skybox.Face.Down, down);
      sky.preloadTextures();

      this.attachChild(sky);
   }

   private void createTerrainBlock() {
      // Generate a random terrain data
      MidPointHeightMap heightMap = new MidPointHeightMap(64, 1f);
      // Scale the data
      Vector3f terrainScale = new Vector3f(20, 0f, 20);
      // create a terrainblock
      tb = new TerrainBlock("terrain", heightMap.getSize(), terrainScale,
            heightMap.getHeightMap(), new Vector3f(0, 0, 0));

      tb.setModelBound(new BoundingBox());
      tb.updateModelBound();

      // assign the texture to the terrain
      TextureState ts = display.getRenderer().createTextureState();
      ts.setEnabled(true);
      Texture t = TextureManager.loadTexture(Skybox.class.getClassLoader()
            .getResource("netjava/robo3d/resource/image/terrain.jpg"),
            Texture.MinificationFilter.BilinearNearestMipMap,
            Texture.MagnificationFilter.Bilinear);
      ts.setTexture(t);
      tb.setRenderState(ts);
      this.attachChild(tb);
   }

   public void update(float interpolation) {
      sky.setLocalTranslation(cam.getLocation());
      updateGeometricState(interpolation, true);
   }
}

someone plz help~ :slight_smile:

Good quality code.



I suggest that you display the world bounds of the TerrainBlock after it is set up.



You have Y scale for the TerrainBlock set to 0.  That will make every returned elevation 0.  See occurrences of "stepScale.y" in TerrainBlock.getHeight(float, float).

The fact that you see the Skybox (which is by default LightCombineMode.Off) and not the rest would point to a lighting problem. Just for testing, set the lightcombinemode to off for the scene nodes. if it turns up its a lighting problem. in that case you could set the colors for the DirectionalLight you create, global ambient and dont forget material for the scene geometries.

dhdd said:

The fact that you see the Skybox (which is by default LightCombineMode.Off) and not the rest would point to a lighting problem. Just for testing, set the lightcombinemode to off for the scene nodes. if it turns up its a lighting problem. in that case you could set the colors for the DirectionalLight you create, global ambient and dont forget material for the scene geometries.

thank you for you useful reply, i'wll try out to see if it is the problem of lighting. thanks again.

Hate to push an 11 month old thread, but I just encountered the exactly same problem.

The interesting part:

The project definitely works on another computer of mine (I merely copied it) - and furthermore, it’s basically TestWalkingChar.java, so it should definitely work!



Aside from the fact that altering the lighting might fix the problem (might it?), any ideas what could be causing it?

A graphics card not supporting Open GL lighting or other basic features sounds a little odd :confused:





€: On a side-note: There are no exceptions thrown, and the jME-log seems to be exactly the same on both machines from what I can tell

Lights missing in the scene? Might be that on an older graphics card the system falls back to a shader that works without light.

This problem looks like, the lighting material fails on the older graphic card thus rendering black objects.The sky material however seems to work.



Are you sure you don’t have an error in the log? Not a java exception but a shader compilation problem with the complete output of the shader code?

FYI. I have problems with black textures as well. Using plain color i have no problems seeing the objects, but as i apply a simple colormap to them (using the code from HelloAsset, basically), and a light, it all goes black.

I’ve tested both with a direcitonal and point light, and the code matches that of HelloAsset.



Thinking it might be a compatibility issue, i ran a couple of tests (namely TestManyLights and TestNormalMaps).

TestManyLights turned out completely black (not the intention i’m sure).

TestNormalMaps showed me black and white sphere with a narrow strip of “dusk” in between.



My computer is a laptop with integrated graphics chip; ATI Mobility Radeon HD 4650.

Mid-end when i bought it almost a year ago. Supports open gl 3.2 according to the specs. Running on Win 7.

To solve my own problem; It was a driver issue. Got fresh ones, and now it’s working fine. I guess i’m too used to automatic updates nowadays.



Could possibly be the problem of dreamer as well?

Nope, unfortunately not - I reproduced it on my friends laptop as well - both up to date with drivers but some really sucky graphic cards :frowning:



On the bright side - there’s definitely some output bout the problem now - some todo-stuff and a description on what the problems is (light problems with some graphic cards)

Could’ve sworn that output wasn’t there when I first tried though! xD



Well, with that todo I guess it’s a recorded problem and I should merely wait (not that big of a deal)

If anyone’s still interested in the output though I can fetch that laptop this weekend and paste it here.

Please paste it here. I don’t remember any “TODOs” being printed out …

Here you go :slight_smile:

Hope this is at least related to the problem - not 100% certain :wink:



[java]29.10.2010 01:2:12 com.jme3.renderer.lwjgl.LwgjlRenderer updateShaderSourceData

WARNUNG: #define USE_TEXTURE 1

// TODO: Fix this so normal particles don’t need it.

// Only needed for certain GPUs.

#version 120



#ifdef USE_TEXTURE

uniform sampler2D m_Texture;

varying vec4 texCoord;

#endif



varying vec4 color;



void main(){

if (color.a <= 0.01)

discard;



#ifdef USE_TEXTURE

#ifdef POINT_SPRITE

vec2 uv = mix(texCoord.xy, texCoord.zw, gl_PointCoord.xy);

#else

vec2 uv = texCoord.xy;

#endif

gl_FragColor = texture2D(m_Texture, uv) * color;

#else

gl_FragColor = color;

#endif

}[/java]

Okay. Yeah this is a known issue, it will be fixed soon.

Alrighty, thanks! :smiley: