#ifdef HAS_FOW
// Get the x,z location of the vertex in world space
vec2 worldXz = (TransformWorld(modelSpacePos)).xz;
// Change the world space coordinate to texture space 0..1
vec2 fowUv = worldXz - vec2(0, 0); // use your actual values here in format like 0.0
fowUv.xy *= vec2(1024, 1024);
// Sample the texture
vec4 fow = texture2D(m_FowMap, worldXz);
// adjust lighting by the fog of war value
DiffuseSum *= vec4(fow.rgb, 1.0);
AmbientSum *= fow.rgb;
SpecularSum *= fow.rgb;
#endif
public Texture2D image() {
// Create the raw FOW overlay image
int size = 1024;
ByteBuffer data = BufferUtils.createByteBuffer(size * size * 4); // square image, four bytes per color
Image image = new Image(Image.Format.ABGR8, size, size, data, ColorSpace.Linear);
// Create a raster that we can draw to
ImageRaster raster = ImageRaster.create(image);
for( int i = 0; i < 1024; i++ ) {
for( int j = 0; j < 1024; j++ ) {
float f = (1f - i/1024) * (1f - j/1024);
ColorRGBA color = new ColorRGBA(f, f, f, 1.0f);
raster.setPixel(i, j, color);
}
}
// Create the texture to set to the FowMap on materials
Texture2D fowMap = new Texture2D(image);
return fowMap;
}
Something is wrong I seem to only see grey like this not the gradient
I don’t know about image blending and what you’ve provided has given me a lot of insight, but now I can’t pinpoint what the problem is and I need your help.
#ifdef HAS_FOW
// Get the x,z location of the vertex in world space
vec2 worldXz = (TransformWorld(modelSpacePos)).xz;
// Change the world space coordinate to texture space 0..1
vec2 fowUv = worldXz - vec2(0, 0); // use your actual values here in format like 0.0
fowUv /= vec2(1024.0, 1024.0);
// Sample the texture
vec4 fow = texture2D(m_FowMap, worldXz);
// adjust lighting by the fog of war value
DiffuseSum *= vec4(fow.rgb, 1.0);
AmbientSum *= fow.rgb;
SpecularSum *= fow.rgb;
#endif
This is the vertex shader code I’m currently using
I fixed that line you were talking about.
Do you have any filter post processing or anything set?
I’m kind of at a loss. It’s probably something simple but I’m not sure what. Now is the part where I would do some debugging to try to figure out what’s really happening.
Maybe after this line:
fowUv /= vec2(1024.0, 1024.0);
Temporarily add:
fowUv = vec2(0.0, 0.0);
…see what happens. I expect everything to be black.
Then try instead:
fowUv = vec2(1.0, 1.0);
…see what happens. I expect everything to be the normal terrain color.
What is the normal terrain color, by the way?
After that, you could try confirming that the uv math is right.
After:
DiffuseSum *= vec4(fow.rgb, 1.0);
Add a line like:
DiffuseSum = vec4(fowUv.x, fowUv.y, 0.0, 1.0);
I’d expect that to be a very colorful gradient over the whole map.
Oh yeah you reminded me I don’t seem to have added a picture of the terrain yet
package com.mygame;
import com.jme3.app.SimpleApplication;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.material.RenderState.FaceCullMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Spatial;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.debug.Arrow;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
import com.jme3.texture.Image;
import com.jme3.texture.Texture2D;
import com.jme3.texture.image.ColorSpace;
import com.jme3.texture.image.ImageRaster;
import com.jme3.util.BufferUtils;
import com.jme3.util.SkyFactory;
import java.nio.ByteBuffer;
public class SimpleFogGridApp extends SimpleApplication {
Spatial sky2;
Material material;
boolean booleanMat=true;
public static void main(String[] args) {
SimpleFogGridApp app = new SimpleFogGridApp();
AppSettings setting = new AppSettings(true);
setting.setWindowSize(1920, 1080);
app.setSettings(setting);
app.start();
}
@Override
public void simpleInitApp() {
sky2 = SkyFactory.createSky(assetManager, "Textures/Sky/Bright/BrightSky.dds", SkyFactory.EnvMapType.CubeMap);
rootNode.attachChild(sky2);
// 创建X、Y、Z方向的箭头,作为参考坐标系。
createArrow(new Vector3f(5, 0, 0), ColorRGBA.Green);
createArrow(new Vector3f(0, 5, 0), ColorRGBA.Red);
createArrow(new Vector3f(0, 0, 5), ColorRGBA.Blue);
// Define vertices for the grid
//定义网格顶点
int width = 1024;
int height = 1024;
float spacing = 1f;
float[] vertices = new float[width * height * 3];
float[] texCoords = new float[height * width * 2]; // Added UV coordinates
for (int x = 0; x < height; x++) {
for (int z = 0; z < width; z++) {
vertices[(x * width + z) * 3] = z * spacing;
vertices[(x * width + z) * 3 + 1] = 0;
vertices[(x * width + z) * 3 + 2] = x * spacing;
// Calculate UV coordinates
texCoords[(x * width + z) * 2] = (float) x / (height - 1);
texCoords[(x * width + z) * 2 + 1] = (float) z / (height - 1);
}
}
// Define indices to create triangles
int[] indices = new int[(width - 1) * (height - 1) * 6];
int idx = 0;
for (int x = 0; x < width - 1; x++) {
for (int z = 0; z < height - 1; z++) {
int topLeft = x * height + z;
int topRight = topLeft + 1;
int bottomLeft = (x + 1) * height + z;
int bottomRight = bottomLeft + 1;
// First triangle 第一个三角形
indices[idx++] = topLeft;
indices[idx++] = bottomLeft;
indices[idx++] = topRight;
// Second triangle 第二个三角形
indices[idx++] = topRight;
indices[idx++] = bottomLeft;
indices[idx++] = bottomRight;
}
}
// Create a Mesh
Mesh mesh = new Mesh();
mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
mesh.setBuffer(Type.Index, 3, BufferUtils.createIntBuffer(indices));
mesh.setBuffer(VertexBuffer.Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoords)); // Set UV coordinates
mesh.updateBound();
// Create a Geometry to display the mesh
Geometry gridGeometry; gridGeometry = new Geometry("Grid", mesh);
// Create a material and set its color "Shaders/FogOfWar/Fog.j3md"
if(booleanMat){
material = new Material(assetManager, "Shaders/FogOfWar/FOWLighting.j3md");
material.setBoolean("HasFow", true);
material.setTexture("FowMap", image());
material.setTexture("LightMap", assetManager.loadTexture("Textures/map/dirt.png"));
//material.getAdditionalRenderState().setWireframe(true);
material.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);
}else{
material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
material.setTexture("ColorMap", image());
}
gridGeometry.setMaterial(material);
// Attach the gridGeometry to the rootNode
rootNode.attachChild(gridGeometry);
flyCam.setMoveSpeed(100f);
// // 定向光
// DirectionalLight sun = new DirectionalLight();
// sun.setDirection(new Vector3f(-1, -2, -3));
// 环境光
AmbientLight ambient = new AmbientLight();
// 调整光照亮度
ColorRGBA lightColor = new ColorRGBA();
//sun.setColor(lightColor.mult(0.8f));
ambient.setColor(lightColor.mult(0.2f));
//rootNode.addLight(sun);
rootNode.addLight(ambient);
}
@Override
public void simpleUpdate(float tpf) {
}
/**
* 创建一个箭头
*
* @param vec3 箭头向量
* @param color 箭头颜色
*/
private void createArrow(Vector3f vec3, ColorRGBA color) {
// 创建材质,设定箭头的颜色
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", color);
mat.getAdditionalRenderState().setWireframe(true);
// 创建几何物体,应用箭头网格。
Geometry geom = new Geometry("arrow", new Arrow(vec3));
geom.setMaterial(mat);
// 添加到场景中
rootNode.attachChild(geom);
}
public Texture2D image() {
// Create the raw FOW overlay image
int size = 1024;
ByteBuffer data = BufferUtils.createByteBuffer(size * size * 4); // square image, four bytes per color
Image image = new Image(Image.Format.ABGR8, size, size, data, ColorSpace.Linear);
// Create a raster that we can draw to
ImageRaster raster = ImageRaster.create(image);
for( int i = 0; i < 1024; i++ ) {
for( int j = 0; j < 1024; j++ ) {
float f = (1f - i/1024) * (1f - j/1024);
ColorRGBA color = new ColorRGBA(f, f, f, 1.0f);
raster.setPixel(i, j, color);
}
}
// Create the texture to set to the FowMap on materials
Texture2D fowMap = new Texture2D(image);
return fowMap;
}
}
Here’s the example I’m currently using I’ve added a terrain image
I’m not sure if it’s something in my code that conflicts with what you’ve provided I’ve put the example I’m using above.
DiffuseSum = vec4(fowUv.x, fowUv.y, 0.0, 1.0);
Nothing seems to change when I try this either, which makes me wonder if it’s a problem with my UVs
But when I look at the LightMap I added on there doesn’t seem to be an error.
I tried to use the method you provided
But all three attempts resulted in the same picture.
I turned off the terrain texture (which seems to make it more visible).
Here are the results of the attempt
#ifdef HAS_FOW
// Get the x,z location of the vertex in world space
vec2 worldXz = (TransformWorld(modelSpacePos)).xz;
// Change the world space coordinate to texture space 0..1
vec2 fowUv = worldXz - vec2(0, 0); // use your actual values here in format like 0.0
fowUv /= vec2(1024.0, 1024.0);
fowUv = vec2(0, 0);
// Sample the texture
vec4 fow = texture2D(m_FowMap, worldXz);
// adjust lighting by the fog of war value
DiffuseSum *= vec4(fow.rgb, 1.0);
AmbientSum *= fow.rgb;
SpecularSum *= fow.rgb;
#endif
#ifdef VERTEX_COLOR
AmbientSum *= inColor.rgb;
DiffuseSum *= inColor;
#endif
#ifdef HAS_FOW
// Get the x,z location of the vertex in world space
vec2 worldXz = (TransformWorld(modelSpacePos)).xz;
// Change the world space coordinate to texture space 0..1
vec2 fowUv = worldXz - vec2(0, 0); // use your actual values here in format like 0.0
fowUv /= vec2(1024.0, 1024.0);
fowUv = vec2(1, 1);
// Sample the texture
vec4 fow = texture2D(m_FowMap, worldXz);
// adjust lighting by the fog of war value
DiffuseSum *= vec4(fow.rgb, 1.0);
AmbientSum *= fow.rgb;
SpecularSum *= fow.rgb;
#endif
#ifdef HAS_FOW
// Get the x,z location of the vertex in world space
vec2 worldXz = (TransformWorld(modelSpacePos)).xz;
// Change the world space coordinate to texture space 0..1
vec2 fowUv = worldXz - vec2(0, 0); // use your actual values here in format like 0.0
fowUv /= vec2(1024.0, 1024.0);
//fowUv = vec2(1, 1);
// Sample the texture
vec4 fow = texture2D(m_FowMap, worldXz);
// adjust lighting by the fog of war value
DiffuseSum = vec4(fowUv.x, fowUv.y, 0.0, 1.0);
//DiffuseSum *= vec4(fow.rgb, 1.0);
AmbientSum *= fow.rgb;
SpecularSum *= fow.rgb;
#endif
#ifdef HAS_FOW
// Get the x,z location of the vertex in world space
vec2 worldXz = (TransformWorld(modelSpacePos)).xz;
// Change the world space coordinate to texture space 0..1
vec2 fowUv = worldXz - vec2(0, 0); // use your actual values here in format like 0.0
fowUv /= vec2(1024.0, 1024.0);
// Sample the texture
vec4 fow = texture2D(m_FowMap, worldXz);
// adjust lighting by the fog of war value
DiffuseSum *= vec4(fow.rgb, 1.0);
AmbientSum *= fow.rgb;
SpecularSum *= fow.rgb;
#endif
#ifdef VERTEX_COLOR
AmbientSum *= inColor.rgb;
DiffuseSum *= inColor;
#endif
I don’t know if Big this is what you expected (I’m guessing not)
#ifdef HAS_FOW
// Get the x,z location of the vertex in world space
vec2 worldXz = (TransformWorld(modelSpacePos)).xz;
// Change the world space coordinate to texture space 0..1
vec2 fowUv = worldXz - vec2(0, 0); // use your actual values here in format like 0.0
fowUv /= vec2(1024.0, 1024.0);
// Sample the texture
vec4 fow = texture2D(m_FowMap, worldXz);
// adjust lighting by the fog of war value
DiffuseSum *= vec4(fow.rgb, 1.0);
AmbientSum *= fow.rgb;
SpecularSum *= fow.rgb;
#endif
DiffuseSum = vec4(1.0, 0.0, 0.0, 1.0);
#ifdef VERTEX_COLOR
AmbientSum *= inColor.rgb;
DiffuseSum *= inColor;
#endif
#ifdef HAS_FOW
// Get the x,z location of the vertex in world space
vec2 worldXz = (TransformWorld(modelSpacePos)).xz;
// Change the world space coordinate to texture space 0..1
vec2 fowUv = worldXz - vec2(0, 0); // use your actual values here in format like 0.0
fowUv /= vec2(1024.0, 1024.0);
// Sample the texture
vec4 fow = texture2D(m_FowMap, worldXz);
// adjust lighting by the fog of war value
DiffuseSum *= vec4(fow.rgb, 1.0);
AmbientSum *= fow.rgb;
SpecularSum *= fow.rgb;
#endif
#ifdef VERTEX_COLOR
AmbientSum *= inColor.rgb;
DiffuseSum *= inColor;
#endif
DiffuseSum = vec4(1.0, 0.0, 0.0, 1.0);
package com.mygame;
import com.jme3.app.SimpleApplication;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.shape.Box;
import com.jme3.texture.Image;
import com.jme3.texture.Texture2D;
import com.jme3.texture.image.ColorSpace;
import com.jme3.texture.image.ImageRaster;
import com.jme3.util.BufferUtils;
import java.nio.ByteBuffer;
/**
* 你的第一个jME3程序
* @author yanmaoyuan
*/
public class JmeBox extends SimpleApplication {
/**
* 初始化3D场景,显示一个方块。
*/
@Override
public void simpleInitApp() {
Mesh box = new Box(1, 1, 1);
Material mat = new Material(assetManager, "Shaders/FogOfWar/FOWLighting.j3md");
mat.setBoolean("HasFow", true);
mat.setTexture("FowMap", image());
Geometry geom = new Geometry("Box");
geom.setMesh(box);
geom.setMaterial(mat);
// 环境光
AmbientLight ambient = new AmbientLight();
rootNode.attachChild(geom);
rootNode.addLight(ambient);
}
public static void main(String[] args) {
// 启动jME3程序
JmeBox app = new JmeBox();
app.start();
}
public Texture2D image() {
// Create the raw FOW overlay image
int size = 1024;
ByteBuffer data = BufferUtils.createByteBuffer(size * size * 4); // square image, four bytes per color
Image image = new Image(Image.Format.ABGR8, size, size, data, ColorSpace.Linear);
// Create a raster that we can draw to
ImageRaster raster = ImageRaster.create(image);
for( int i = 0; i < 1024; i++ ) {
for( int j = 0; j < 1024; j++ ) {
float f = (1f - i/1024) * (1f - j/1024);
ColorRGBA color = new ColorRGBA(f, f, f, 1.0f);
raster.setPixel(i, j, color);
}
}
// Create the texture to set to the FowMap on materials
Texture2D fowMap = new Texture2D(image);
return fowMap;
}
}
It didn’t turn red.
I repeated the previous test with no changes as shown in this screenshot
additions:
Although I know relatively little about shaders, I’ve come up with a relatively simple way to deal with it that is to expand the resolution to make 1024*8
He looks like this.
You habe to validate the texture coordinates first. as long as printing the uv does not produces a nice gradient you end up working around the primary issue